forked from ChomeNS/chomens-bot-java
Compare commits
556 commits
Author | SHA1 | Date | |
---|---|---|---|
daba9d2374 | |||
2fb5dad02c | |||
c4e7c9e799 | |||
0960e8e834 | |||
192a6a0922 | |||
0ae4f32c3a | |||
32f93f247e | |||
ef3298e3f8 | |||
7440dccc9b | |||
313c4389a1 | |||
3d6f1193e6 | |||
233b386af9 | |||
12b8359c6b | |||
9a81921baa | |||
bcaf59c19d | |||
78f84f1c71 | |||
ba53a265c5 | |||
3960bf1fab | |||
21100ee7b1 | |||
12d01932c1 | |||
f542bb6fc1 | |||
23b7c3351a | |||
271c1e797a | |||
5cd9fb3959 | |||
7e5d3c8fc8 | |||
ee8d68c4e3 | |||
67774125c9 | |||
b21104c306 | |||
76e874e077 | |||
48ffc7c01c | |||
f68ce719f9 | |||
9afbdc26b3 | |||
a368cc6f13 | |||
393715f9da | |||
263ea7458c | |||
95a1f58fe1 | |||
040be16246 | |||
c68e300047 | |||
0105ee95a2 | |||
007e4b5b59 | |||
edbd96366b | |||
53a3d95032 | |||
8c8a058f38 | |||
ad5e203417 | |||
8fd2f2ebb3 | |||
f3d3355bd2 | |||
37e69779ae | |||
cdaa82bdfa | |||
8ab00505e4 | |||
3f0ae861e6 | |||
0f28e8c900 | |||
b4f0958202 | |||
d1d7b9fb29 | |||
5b56f411a1 | |||
a60baad6f3 | |||
5f569246af | |||
a3e0482604 | |||
c7a578f1d0 | |||
8ab8ecd2f7 | |||
8dad298c50 | |||
b699cb2f7a | |||
c5da3a8689 | |||
76e75f3601 | |||
879c1acf1d | |||
2b1a4067ab | |||
092f83ade4 | |||
e9cc4f1499 | |||
f497651043 | |||
839b202d11 | |||
3f7625895f | |||
c392db1903 | |||
7660ac57bc | |||
56c7aa5493 | |||
4be485df0f | |||
ca61686a70 | |||
8e743b2014 | |||
0c89ffc983 | |||
66f7754b78 | |||
e8a4c03e8c | |||
dc38ef86c6 | |||
cea28ffd50 | |||
a7792651bb | |||
d9608f25cb | |||
0e8bd4404b | |||
9030752007 | |||
c952ba5a6f | |||
a915cbbe4b | |||
0330cc2f75 | |||
958730ec99 | |||
2e382da7c3 | |||
5d91373e6b | |||
8c1ea040cf | |||
b38f2a7e1b | |||
2b23074b1e | |||
e8eb2f3b4d | |||
9aea972690 | |||
8a868052f5 | |||
14ab8a7bda | |||
3db1002af1 | |||
3bf8b78e28 | |||
e30132b00d | |||
5884718994 | |||
eff32f8437 | |||
4951286575 | |||
059664ca0c | |||
21d79192c6 | |||
5d7b576f53 | |||
711f3e2885 | |||
5dc3be1994 | |||
a01f749577 | |||
a3ccacf758 | |||
a30f4661b2 | |||
05601e4cef | |||
d362919c55 | |||
5f4292b240 | |||
66ab8ceb07 | |||
c8c82df0b4 | |||
527517ab9e | |||
9d9955444b | |||
b8068d72ff | |||
4e15434863 | |||
96f5f66f01 | |||
a7f6cac49b | |||
572f4c2119 | |||
5c87e95c30 | |||
dd10e6f1ab | |||
a744c16f20 | |||
7b6f50cfab | |||
76b7df54e2 | |||
896b75c40f | |||
d4a56051ce | |||
4fbff56231 | |||
b1925edf00 | |||
c90840265a | |||
2ab3a4322a | |||
6a93b3ef63 | |||
00e7bd59c0 | |||
2b8185222a | |||
ac319b6281 | |||
8290473631 | |||
788f5e88e6 | |||
4861443bd8 | |||
181b907ac7 | |||
db56afd319 | |||
ac9c26bcd0 | |||
ceb9bfd34d | |||
8b4286bc31 | |||
f1d24b8a59 | |||
b8ea989026 | |||
1bb4d1713e | |||
061371f40b | |||
14bdf45c89 | |||
2f65276225 | |||
53860c3c5a | |||
2e79c7599f | |||
d639fa7f6b | |||
2cc5e6dc9c | |||
0bd20d2163 | |||
56e3aba21a | |||
20d89b14d7 | |||
bb3635137c | |||
d746140005 | |||
a3b6f7fecf | |||
decd15a926 | |||
346c55c3d6 | |||
ef15c45619 | |||
c6e8585246 | |||
fcc816d0c9 | |||
4c5fa6d733 | |||
f2250c656e | |||
5cd1cc8976 | |||
f06369d112 | |||
6cf6fa1ae0 | |||
97152d7bd0 | |||
b7807686d0 | |||
26ca1eb830 | |||
de43240755 | |||
ae03603e9d | |||
8bce548c09 | |||
b9386f86e1 | |||
4685e37b4f | |||
30a7bcd24b | |||
0ca9990d08 | |||
b9207ffb0c | |||
a5602d1a01 | |||
9557231010 | |||
359cf9a19c | |||
9e486ebbe1 | |||
057ee9095f | |||
ee6811ccd2 | |||
563df838c5 | |||
a87e1df9c1 | |||
79bb8cc877 | |||
dbd4cdb656 | |||
185b6d4305 | |||
dfdc959a16 | |||
7cd77fe850 | |||
29ca22101a | |||
21ba029e42 | |||
0c29f2f8ca | |||
58fcd586a4 | |||
70bf2574cf | |||
76eadb1472 | |||
49209ab8b4 | |||
94f90575d8 | |||
72cbad0a99 | |||
f811000a07 | |||
ed4e7573a9 | |||
2764673f21 | |||
31f54ee8f8 | |||
ed71cdc55a | |||
54f0f36952 | |||
297b84801f | |||
ffdfcb421d | |||
82aec3869b | |||
80aec4fca8 | |||
dd2b8ce26d | |||
dffc22674b | |||
93f582bba0 | |||
11f08138fe | |||
16cde68c4a | |||
31ace7334e | |||
50ba4e1c41 | |||
37326ede51 | |||
572d175c17 | |||
1a2d9c136c | |||
607a131fa5 | |||
00a374104d | |||
5e06c7cf8b | |||
c0390b806f | |||
1c7cd3038c | |||
af67c228ce | |||
59749d85df | |||
ae91b3d78b | |||
65cc3971af | |||
ac44bedf8c | |||
a711e21437 | |||
db1be06b17 | |||
884c525f2e | |||
386bf69e7a | |||
8ce017f7d0 | |||
e80530c847 | |||
13385de5d5 | |||
9d6b0d8dc4 | |||
8c4aae3401 | |||
b8bea93754 | |||
1d7190dd44 | |||
58e722ba06 | |||
7617818720 | |||
2fd205bd61 | |||
6edb683274 | |||
90323d3552 | |||
156a5af47f | |||
bb0900eeb6 | |||
dddead69ba | |||
3ee759211b | |||
e0f0b4c174 | |||
6c98da4184 | |||
2196e822d5 | |||
92c4726fcd | |||
6f92ea38d5 | |||
e68f4c874c | |||
821bfe2626 | |||
363d7a9270 | |||
9e7351dca8 | |||
9c6c35677c | |||
56aae42a94 | |||
c70e8b5779 | |||
8c65eb0ec1 | |||
1f2355aa77 | |||
209cd1a6dd | |||
7c6c2c23ce | |||
50addd1abd | |||
517e685c8d | |||
1e6421a17c | |||
d9e22906ef | |||
dd629d1dfa | |||
450b2a7b51 | |||
b6133600f5 | |||
05854223b1 | |||
a2b564abf5 | |||
265a35080b | |||
043efe9547 | |||
87ef3b8a95 | |||
e37d3b1a6e | |||
b61d7ee2fa | |||
2740c4d87b | |||
bfbed35c06 | |||
15c8301f65 | |||
90a43ad2c0 | |||
0a8efe0189 | |||
60356a5eea | |||
3b200d8a2b | |||
d77c05389e | |||
cc635ca8c6 | |||
210dd7aaa1 | |||
83ac7632c6 | |||
4a752ef0a2 | |||
185b835f7e | |||
8a9b123f49 | |||
5834a0584a | |||
38aab5d1f6 | |||
6f8fb1d3b6 | |||
37d7bbe2a7 | |||
bed87d2396 | |||
5587565325 | |||
9d6fc74a34 | |||
a933653112 | |||
0d0c8a2bce | |||
0bf8ce54f8 | |||
079c579b0e | |||
5fdb86c81c | |||
85b394c86d | |||
04b0377bd9 | |||
07b61540ef | |||
3ce56fc110 | |||
52130e85ae | |||
04a8d10e1f | |||
f882c15d39 | |||
670c678ced | |||
c6adc4cc0f | |||
04fd9e8e17 | |||
7270354573 | |||
669ddb38f2 | |||
a0e32ad146 | |||
164f097249 | |||
dd0d80f265 | |||
e02de9232d | |||
60350a1adb | |||
8e20cf2285 | |||
3771143e49 | |||
bee4fb5d5b | |||
c86e2714e6 | |||
fb8dd58de1 | |||
d75611ff6f | |||
381b3bdc69 | |||
553def4a3e | |||
0f80598881 | |||
e7ac8f9a7e | |||
65837f2afd | |||
a375818487 | |||
9ad02a35c9 | |||
f6a3cad40a | |||
2a225b9169 | |||
6bc879b1a7 | |||
6bab5e50ec | |||
d75e04b2d3 | |||
a00a77763c | |||
4ef0266d1d | |||
aeb94a871a | |||
fc51221035 | |||
d11eb4d0f6 | |||
f24258ccf2 | |||
7069c7d0ab | |||
2b328c3d0d | |||
b9381755c1 | |||
e58e951943 | |||
c002868c47 | |||
7febe0705a | |||
171b3836df | |||
34acf10e82 | |||
2d67f616be | |||
ece89a68c5 | |||
f3b31bde85 | |||
e1eb52ce2e | |||
7b08c0dc36 | |||
d962fa325b | |||
60bf424f27 | |||
fbe6f1711b | |||
02b9fd4f0b | |||
de4e3e8e96 | |||
e1c04f89a9 | |||
63d6eaa359 | |||
c4504df4ce | |||
e9052c83da | |||
3b4c8f5fda | |||
76034805a0 | |||
0a70b17c6f | |||
bb766652f6 | |||
4e37021b50 | |||
d2fd3860f9 | |||
54be006f7a | |||
2000662247 | |||
c976878997 | |||
f3ffa19bfa | |||
04c7c64c9e | |||
d309e7c96c | |||
ed5b89acba | |||
f4cb86effb | |||
633ae80aac | |||
31236e77b0 | |||
25c353f588 | |||
9d0e67a86e | |||
c8ccdfd561 | |||
3684cde6a7 | |||
2912e6c9c7 | |||
31bdc301be | |||
fc1d88b1d4 | |||
3428ca49ad | |||
eba10601d1 | |||
d44a29528c | |||
b534c57f0f | |||
f91f9ef5ff | |||
fbc68057b8 | |||
1c70b978a9 | |||
c1d269b812 | |||
2462fdd361 | |||
98eace0386 | |||
c682597fb8 | |||
859b599af9 | |||
8b5e706769 | |||
4061bc5874 | |||
6ba3a1cd2d | |||
ea671ec4d2 | |||
186d2a4f4c | |||
10a7f1ab1c | |||
9224c6661c | |||
6c9766b25a | |||
e4256436ad | |||
dbb8c2479f | |||
7d72776806 | |||
4063385ac2 | |||
b73940453d | |||
13ad030b82 | |||
fc9b993c49 | |||
90fe3d1145 | |||
4478d0287d | |||
9434c16e70 | |||
655a52b28d | |||
e96e8bc951 | |||
ae7fe63846 | |||
54389f2e2b | |||
a8e4b65355 | |||
af78fe2611 | |||
d19e02b3a7 | |||
a1a3be3ee5 | |||
72fde45465 | |||
6a524a6595 | |||
eacd91a369 | |||
ae8be94be3 | |||
6164483e11 | |||
7c861e1869 | |||
ebc7560d2e | |||
793b1538a0 | |||
4f93704459 | |||
d503416337 | |||
fd0d69c000 | |||
5e82250e37 | |||
f3e502682c | |||
da998c050a | |||
693cfe0f42 | |||
0cf8d94ff9 | |||
145a7fe2fe | |||
b7f2023977 | |||
a90eec985a | |||
f7f3813ec8 | |||
1acc0fdbfd | |||
1d8ec221ad | |||
82ecf3833d | |||
309683bde3 | |||
eed3073ee7 | |||
ba5f88df36 | |||
cb487b5939 | |||
e4743fd503 | |||
0bae8b268c | |||
6cbcdd8737 | |||
d20f7532bf | |||
15ea941da7 | |||
c3ae616292 | |||
9413b493ea | |||
8948d04495 | |||
4d9c1ca99b | |||
e50f9cf433 | |||
052e57a799 | |||
9b675bfed4 | |||
4ace6afccc | |||
0a42fb68b2 | |||
9c75b6309f | |||
90aef4e594 | |||
a1da3dbc2c | |||
a912ee012a | |||
05337f0274 | |||
2df59435d0 | |||
8217606437 | |||
497155a827 | |||
eba4f92e45 | |||
8e84565090 | |||
3a25f28635 | |||
54c0efb447 | |||
50dc16bee4 | |||
c504918571 | |||
cdaa625962 | |||
e798a9dc18 | |||
c1efc1c3d5 | |||
36fa5b3f9b | |||
2340991012 | |||
0995c12b70 | |||
e72d9c8bb8 | |||
f5a3599adb | |||
7e42a5cf43 | |||
e9de7eb801 | |||
5a06ee53b6 | |||
6a11f237ef | |||
621f06f2e5 | |||
d09b9b37db | |||
7e4139cebc | |||
634c8cf087 | |||
aa871dc080 | |||
a541371ce1 | |||
ab85cc8e2a | |||
15835d7ac6 | |||
935dfdcb32 | |||
24b7ada58f | |||
6dc47be63e | |||
1d3b51cd3f | |||
1afcfde5e5 | |||
b3beac6c3b | |||
9b320d64b5 | |||
bf70930cd8 | |||
c2bab61c09 | |||
c2cdf8bcf9 | |||
79b6ae13a6 | |||
2c517b7326 | |||
4600eaf942 | |||
f25618d4c1 | |||
cde1e0d07a | |||
5f15ea2d4d | |||
7e09ea3257 | |||
f2c9d3a30e | |||
55f4d1fece | |||
d0d28cc55b | |||
808e29c0af | |||
3782c97d21 | |||
7fba5711d1 | |||
bd4ceda4f1 | |||
20cd93a826 | |||
4ef6e334b0 | |||
e045d88cfc | |||
f83ead52bb | |||
c1be374457 | |||
89dc2e2781 | |||
1ebb798077 | |||
bb0bc090df | |||
36a138becc | |||
651db6c8ce | |||
ed4c171f11 | |||
65bae4ce7d | |||
dc023758f2 | |||
f7187e560f | |||
60a1d069c7 | |||
06522fadcc | |||
392120f28b | |||
975199bf4f | |||
d8c8a9750d | |||
832d6ee5fa | |||
a45477ed1b |
249 changed files with 14817 additions and 8092 deletions
.gitignoreREADME.mdbuild-number.txtbuild.gradlecodestyle.xml
gradle/wrapper
gradlewinspections.xmlsrc/main/java/me/chayapak1/chomens_bot
Bot.javaConfiguration.javaMain.java
chatParsers
chomeNSMod
chunk
command
Command.javaCommandContext.javaCommandException.javaCommonFlags.javaConsoleCommandContext.javaDiscordCommandContext.javaPlayerCommandContext.javaTrustLevel.java
contexts
commands
AuthCommand.javaBotVisibilityCommand.javaBruhifyCommand.javaClearChatCommand.javaClearChatQueueCommand.javaCloopCommand.javaCommandBlockCommand.javaConsoleCommand.javaCowsayCommand.javaEchoCommand.javaEndCommand.javaEvalCommand.javaFilterCommand.javaFindAltsCommand.javaGrepLogCommand.javaHelpCommand.javaIPFilterCommand.javaInfoCommand.javaKickCommand.javaListCommand.javaMailCommand.javaMusicCommand.javaNetCommandCommand.javaNetMessageCommand.javaPCrashCommand.javaRandomTeleportCommand.javaRefillCoreCommand.javaRestartCommand.javaScreenshareCommand.javaSeenCommand.javaServerEvalCommand.javaStopCommand.javaTPSBarCommand.javaTestCommand.javaTimeCommand.javaTranslateCommand.javaUUIDCommand.javaUrbanCommand.javaValidateCommand.javaWeatherCommand.javaWhitelistCommand.javaWikipediaCommand.java
data
CommandLoop.javaFilteredPlayer.javaIRCMessage.javaMail.javaPlayerEntry.javaRotation.javaTeam.java
bossbar
chat
chomeNSMod
chunk
cloop
color
entity
eval
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -9,8 +9,14 @@ run/
|
|||
*.ipr
|
||||
*.iws
|
||||
|
||||
# Exploits plugin
|
||||
# Exploits stuff
|
||||
src/main/java/me/chayapak1/chomens_bot/plugins/ExploitsPlugin.java
|
||||
src/main/java/me/chayapak1/chomens_bot/data/exploitMethods/
|
||||
|
||||
# Testing plugins
|
||||
src/main/java/me/chayapak1/chomens_bot/plugins/testing
|
||||
|
||||
# Bot's files (made when running via ./gradlew run)
|
||||
config.yml
|
||||
logs/
|
||||
songs/
|
||||
|
|
27
README.md
27
README.md
|
@ -1,27 +1,22 @@
|
|||
# ChomeNS Bot Java
|
||||
A Java verison of ChomeNS Bot.
|
||||
A Java version of ChomeNS Bot.
|
||||
|
||||
# Compiling
|
||||
You will see that the exploits plugin is missing because I gitignored it to prevent exploit leaks
|
||||
|
||||
To make this successfully compile just make `ExploitsPlugin.java` in the plugins folder and add this code:
|
||||
To make this successfully compile, you will have to fix the missing `ExploitsPlugin.java` in the `plugins` package, and also some enums related to it.
|
||||
|
||||
```java
|
||||
package me.chayapak1.chomens_bot.plugins;
|
||||
After that, you can now run `./gradlew build` to actually get the `.jar` file.
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
The .jar file will be at `build/libs`, to run the bot simply do `java -jar chomens_bot-rolling-all.jar`
|
||||
|
||||
import java.util.UUID;
|
||||
# Development
|
||||
|
||||
public class ExploitsPlugin {
|
||||
public ExploitsPlugin (Bot bot) {}
|
||||
When commiting your changes, please use my code style.
|
||||
|
||||
public void kick (UUID uuid) {}
|
||||
|
||||
public void pcrash (UUID uuid) {}
|
||||
}
|
||||
```
|
||||
In IntelliJ IDEA:
|
||||
|
||||
Then at the root of the project run `./gradlew build` to build.
|
||||
`Ctrl + Alt + S`, search `Code Style`, go to `Java`, click gear icon, `Import Scheme -> IntelliJ IDEA code style XML`,
|
||||
use the `codestyle.xml` file in this repository
|
||||
|
||||
The .jar file will be at `build/libs`, to run the bot do `java -jar chomens_bot-rolling-all.jar`
|
||||
`Ctrl + Alt + Shift + H`, click `Configure Inspections...`, click gear icon, `Import Profile...`,
|
||||
use the `inspections.xml` file in this repository
|
||||
|
|
1
build-number.txt
Normal file
1
build-number.txt
Normal file
|
@ -0,0 +1 @@
|
|||
3459
|
83
build.gradle
83
build.gradle
|
@ -1,3 +1,5 @@
|
|||
import java.text.SimpleDateFormat
|
||||
|
||||
plugins {
|
||||
id 'java'
|
||||
id 'application'
|
||||
|
@ -7,7 +9,7 @@ plugins {
|
|||
group = 'me.chayapak1'
|
||||
version = 'rolling'
|
||||
description = 'ChomeNS Bot'
|
||||
java.sourceCompatibility = JavaVersion.VERSION_17
|
||||
java.sourceCompatibility = JavaVersion.VERSION_21
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
|
@ -39,28 +41,83 @@ repositories {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'org.geysermc.mcprotocollib:protocol:1.21-SNAPSHOT'
|
||||
implementation 'net.kyori:adventure-text-serializer-ansi:4.15.0'
|
||||
implementation 'com.google.code.gson:gson:2.11.0'
|
||||
implementation 'com.google.guava:guava:31.1-jre'
|
||||
implementation 'org.jline:jline:3.23.0'
|
||||
implementation 'ch.qos.logback:logback-classic:1.5.11'
|
||||
implementation 'org.geysermc.mcprotocollib:protocol:1.21.5-SNAPSHOT'
|
||||
implementation 'net.kyori:adventure-text-serializer-plain:4.21.0'
|
||||
implementation 'net.kyori:adventure-text-serializer-legacy:4.21.0'
|
||||
implementation 'net.kyori:adventure-text-serializer-ansi:4.21.0'
|
||||
implementation 'com.google.code.gson:gson:2.13.1'
|
||||
implementation 'com.google.guava:guava:33.4.8-jre'
|
||||
implementation 'com.fasterxml.jackson.core:jackson-databind:2.19.0'
|
||||
implementation 'org.mariadb.jdbc:mariadb-java-client:3.5.3'
|
||||
implementation 'org.jline:jline:3.30.3'
|
||||
implementation 'it.unimi.dsi:fastutil:8.5.15'
|
||||
implementation 'ch.qos.logback:logback-classic:1.5.18'
|
||||
implementation 'com.github.pircbotx:pircbotx:2.3.1'
|
||||
implementation 'com.github.ricksbrown:cowsay:1.1.0'
|
||||
implementation 'org.yaml:snakeyaml:2.0'
|
||||
implementation 'org.luaj:luaj-jse:3.0.1'
|
||||
implementation 'net.dv8tion:JDA:5.0.0-beta.12'
|
||||
implementation 'net.kyori:adventure-text-serializer-legacy:4.15.0'
|
||||
implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.20.0'
|
||||
implementation 'io.socket:socket.io-client:2.1.0'
|
||||
implementation 'org.yaml:snakeyaml:2.4'
|
||||
implementation 'party.iroiro.luajava:luajava:4.0.2'
|
||||
implementation 'party.iroiro.luajava:lua54:4.0.2'
|
||||
runtimeOnly 'party.iroiro.luajava:lua54-platform:4.0.2:natives-desktop' // what is this? is this necessary?
|
||||
implementation 'net.dv8tion:JDA:5.5.1'
|
||||
implementation 'org.apache.logging.log4j:log4j-slf4j-impl:2.24.3'
|
||||
implementation 'io.socket:socket.io-client:2.1.2'
|
||||
implementation 'de.maxhenkel.opus4j:opus4j:2.0.2'
|
||||
implementation 'org.concentus:Concentus:1.0-SNAPSHOT'
|
||||
}
|
||||
|
||||
static def getGitCommitHash() {
|
||||
try {
|
||||
return 'git rev-parse --short HEAD'.execute().text.trim()
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace()
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
static def getGitCommitCount() {
|
||||
try {
|
||||
return 'git rev-list --count HEAD'.execute().text.trim()
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace()
|
||||
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
def buildNumberFile = file("build-number.txt")
|
||||
def buildNumber = 0
|
||||
|
||||
if (buildNumberFile.exists()) {
|
||||
buildNumber = buildNumberFile.text.trim().toInteger() + 1
|
||||
} else {
|
||||
buildNumber = 1
|
||||
}
|
||||
|
||||
buildNumberFile.text = buildNumber
|
||||
|
||||
ext.buildInfo = [
|
||||
gitCommitCount: getGitCommitCount(),
|
||||
compileDate: new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z").format(new Date()),
|
||||
gitCommitHash: getGitCommitHash(),
|
||||
buildNumber: buildNumber,
|
||||
]
|
||||
|
||||
processResources {
|
||||
inputs.property("buildInfo", buildInfo)
|
||||
filesMatching("application.properties") {
|
||||
expand(buildInfo)
|
||||
}
|
||||
}
|
||||
|
||||
application {
|
||||
mainClass = 'me.chayapak1.chomens_bot.Main'
|
||||
}
|
||||
|
||||
run {
|
||||
standardInput = System.in
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
options.encoding = 'UTF-8'
|
||||
}
|
||||
|
|
30
codestyle.xml
Normal file
30
codestyle.xml
Normal file
|
@ -0,0 +1,30 @@
|
|||
<code_scheme name="Project" version="173">
|
||||
<JavaCodeStyleSettings>
|
||||
<option name="GENERATE_FINAL_LOCALS" value="true" />
|
||||
<option name="GENERATE_FINAL_PARAMETERS" value="true" />
|
||||
<option name="VISIBILITY" value="protected" />
|
||||
<option name="SPACE_BEFORE_OPENING_ANGLE_BRACKET_IN_TYPE_PARAMETER" value="true" />
|
||||
<option name="SPACE_BEFORE_DECONSTRUCTION_LIST" value="true" />
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<codeStyleSettings language="JAVA">
|
||||
<option name="RIGHT_MARGIN" value="120" />
|
||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||
<option name="BLANK_LINES_AROUND_METHOD_IN_INTERFACE" value="0" />
|
||||
<option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
|
||||
<option name="SPACE_WITHIN_BRACES" value="true" />
|
||||
<option name="SPACE_WITHIN_ARRAY_INITIALIZER_BRACES" value="true" />
|
||||
<option name="SPACE_BEFORE_METHOD_PARENTHESES" value="true" />
|
||||
<option name="SPACE_BEFORE_ARRAY_INITIALIZER_LBRACE" value="true" />
|
||||
<option name="KEEP_SIMPLE_BLOCKS_IN_ONE_LINE" value="true" />
|
||||
<option name="KEEP_SIMPLE_METHODS_IN_ONE_LINE" value="true" />
|
||||
<option name="KEEP_SIMPLE_LAMBDAS_IN_ONE_LINE" value="true" />
|
||||
<option name="KEEP_SIMPLE_CLASSES_IN_ONE_LINE" value="true" />
|
||||
<option name="KEEP_MULTIPLE_EXPRESSIONS_IN_ONE_LINE" value="true" />
|
||||
</codeStyleSettings>
|
||||
<codeStyleSettings language="kotlin">
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -1,6 +1,6 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
|
||||
networkTimeout=10000
|
||||
validateDistributionUrl=true
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
|
|
3
gradlew
vendored
3
gradlew
vendored
|
@ -86,8 +86,7 @@ done
|
|||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s
|
||||
' "$PWD" ) || exit
|
||||
APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD=maximum
|
||||
|
|
9
inspections.xml
Normal file
9
inspections.xml
Normal file
|
@ -0,0 +1,9 @@
|
|||
<component name="InspectionProjectProfileManager">
|
||||
<profile version="1.0">
|
||||
<option name="myName" value="Project Default" />
|
||||
<inspection_tool class="LocalCanBeFinal" enabled="true" level="WARNING" enabled_by_default="true">
|
||||
<option name="REPORT_VARIABLES" value="true" />
|
||||
<option name="REPORT_PARAMETERS" value="true" />
|
||||
</inspection_tool>
|
||||
</profile>
|
||||
</component>
|
|
@ -1,30 +1,54 @@
|
|||
package me.chayapak1.chomens_bot;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||
import me.chayapak1.chomens_bot.data.color.ColorPalette;
|
||||
import me.chayapak1.chomens_bot.data.listener.Listener;
|
||||
import me.chayapak1.chomens_bot.plugins.*;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import me.chayapak1.chomens_bot.util.RandomStringUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import net.kyori.adventure.key.Key;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.network.BuiltinFlags;
|
||||
import org.geysermc.mcprotocollib.network.ClientSession;
|
||||
import org.geysermc.mcprotocollib.network.Session;
|
||||
import org.geysermc.mcprotocollib.network.event.session.*;
|
||||
import org.geysermc.mcprotocollib.network.factory.ClientNetworkSessionFactory;
|
||||
import org.geysermc.mcprotocollib.network.packet.Packet;
|
||||
import org.geysermc.mcprotocollib.network.tcp.TcpClientSession;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftConstants;
|
||||
import org.geysermc.mcprotocollib.protocol.MinecraftProtocol;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.HandPreference;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.ChatVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.ParticleStatus;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.setting.SkinPart;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundCustomPayloadPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundStoreCookiePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.clientbound.ClientboundTransferPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundClientInformationPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.common.serverbound.ServerboundCustomPayloadPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.cookie.clientbound.ClientboundCookieRequestPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.cookie.serverbound.ServerboundCookieResponsePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.clientbound.ClientboundLoginPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.clientbound.ClientboundGameProfilePacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.ingame.serverbound.ServerboundPlayerLoadedPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.clientbound.ClientboundCustomQueryPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.clientbound.ClientboundLoginCompressionPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.clientbound.ClientboundLoginFinishedPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundCustomQueryAnswerPacket;
|
||||
import org.geysermc.mcprotocollib.protocol.packet.login.serverbound.ServerboundLoginAcknowledgedPacket;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class Bot {
|
||||
private final ArrayList<Listener> listeners = new ArrayList<>();
|
||||
public class Bot extends SessionAdapter {
|
||||
private static final List<String> NEEDS_DELAY_DISCONNECT_REASON = ObjectList.of(
|
||||
"Wait 5 seconds before connecting, thanks! :)",
|
||||
"You are logging in too fast, try again later.",
|
||||
"Connection throttled! Please wait before reconnecting."
|
||||
);
|
||||
|
||||
public final String host;
|
||||
public final int port;
|
||||
|
@ -32,6 +56,7 @@ public class Bot {
|
|||
public final Configuration.BotOption options;
|
||||
|
||||
public final Configuration config;
|
||||
public final ColorPalette colorPalette;
|
||||
|
||||
public final List<Bot> bots;
|
||||
|
||||
|
@ -39,57 +64,69 @@ public class Bot {
|
|||
|
||||
public GameProfile profile;
|
||||
|
||||
public Session session;
|
||||
public ClientSession session;
|
||||
|
||||
private final Map<Key, byte[]> cookies = new HashMap<>();
|
||||
|
||||
private boolean isTransferring = false;
|
||||
|
||||
public boolean printDisconnectedCause = false;
|
||||
|
||||
public int connectAttempts = 0;
|
||||
|
||||
public boolean loggedIn = false;
|
||||
public long loginTime = System.currentTimeMillis();
|
||||
|
||||
public final ExecutorService executorService = Main.executorService;
|
||||
public final ScheduledExecutorService executor = Main.executor;
|
||||
public final ExecutorService executorService = Main.EXECUTOR_SERVICE;
|
||||
public final ScheduledExecutorService executor = Main.EXECUTOR;
|
||||
|
||||
public ConsolePlugin console;
|
||||
public LoggerPlugin logger; // in ConsolePlugin
|
||||
public DiscordPlugin discord; // same for this one too
|
||||
public IRCPlugin irc; // AND same for this one too
|
||||
public final ListenerManagerPlugin listener;
|
||||
public final LoggerPlugin logger;
|
||||
public final TickPlugin tick;
|
||||
public final ChatPlugin chat;
|
||||
public final CommandSpyPlugin commandSpy;
|
||||
public final PositionPlugin position;
|
||||
public final ServerFeaturesPlugin serverFeatures;
|
||||
public final SelfCarePlugin selfCare;
|
||||
public final QueryPlugin query;
|
||||
public final ExtrasMessengerPlugin extrasMessenger;
|
||||
public final WorldPlugin world;
|
||||
public final CorePlugin core;
|
||||
public final TeamPlugin team;
|
||||
public final PlayersPlugin players;
|
||||
public final TabCompletePlugin tabComplete;
|
||||
public final CommandHandlerPlugin commandHandler;
|
||||
public final ChatCommandHandlerPlugin chatCommandHandler;
|
||||
public final BossbarManagerPlugin bossbar;
|
||||
public final MusicPlayerPlugin music;
|
||||
public final TPSPlugin tps;
|
||||
public final EvalPlugin eval;
|
||||
public final TrustedPlugin trusted;
|
||||
public final GrepLogPlugin grepLog;
|
||||
public final BruhifyPlugin bruhify;
|
||||
public final CloopPlugin cloop;
|
||||
public final ExploitsPlugin exploits;
|
||||
public final FilterManagerPlugin filterManager;
|
||||
public final PlayerFilterPlugin playerFilter;
|
||||
public final CommandSuggestionPlugin commandSuggestion;
|
||||
public final MailPlugin mail;
|
||||
public final PacketSnifferPlugin packetSniffer;
|
||||
public final VoiceChatPlugin voiceChat;
|
||||
public final BotSelectorBroadcasterPlugin selectorBroadcaster;
|
||||
public final ChomeNSModIntegrationPlugin chomeNSMod;
|
||||
public final AuthPlugin auth;
|
||||
public final ScreensharePlugin screenshare = null;
|
||||
public final ClearChatNameAnnouncerPlugin clearChatNameAnnouncer;
|
||||
public final WhitelistPlugin whitelist;
|
||||
public final PlayersDatabasePlugin playersDatabase;
|
||||
public final IPFilterPlugin ipFilter;
|
||||
public final RainbowArmorPlugin rainbowArmor;
|
||||
|
||||
public TickPlugin tick;
|
||||
public ChatPlugin chat;
|
||||
public CommandSpyPlugin commandSpy;
|
||||
public PositionPlugin position;
|
||||
public ServerPluginsManagerPlugin serverPluginsManager;
|
||||
public SelfCarePlugin selfCare;
|
||||
public CorePlugin core;
|
||||
public TeamPlugin team;
|
||||
public PlayersPlugin players;
|
||||
public TabCompletePlugin tabComplete;
|
||||
public CommandHandlerPlugin commandHandler;
|
||||
public ChatCommandHandlerPlugin chatCommandHandler;
|
||||
public HashingPlugin hashing;
|
||||
public BossbarManagerPlugin bossbar;
|
||||
public MusicPlayerPlugin music;
|
||||
public TPSPlugin tps;
|
||||
public EvalPlugin eval;
|
||||
public TrustedPlugin trusted;
|
||||
public GrepLogPlugin grepLog;
|
||||
public BruhifyPlugin bruhify;
|
||||
public CloopPlugin cloop;
|
||||
public ExploitsPlugin exploits;
|
||||
public FilterPlugin filter;
|
||||
public CommandSuggestionPlugin commandSuggestion;
|
||||
public MailPlugin mail;
|
||||
public PacketSnifferPlugin packetSniffer;
|
||||
public VoiceChatPlugin voiceChat;
|
||||
public TagPlugin tag;
|
||||
public WorldPlugin world;
|
||||
public AuthPlugin auth;
|
||||
public ScreensharePlugin screenshare;
|
||||
public FormatCheckerPlugin formatChecker;
|
||||
public WhitelistPlugin whitelist;
|
||||
public PlayersPersistentDataPlugin playersPersistent;
|
||||
public IPFilterPlugin ipFilter;
|
||||
|
||||
public Bot (Configuration.BotOption botOption, List<Bot> bots, Configuration config) {
|
||||
public Bot (
|
||||
final Configuration.BotOption botOption,
|
||||
final List<Bot> bots,
|
||||
final Configuration config
|
||||
) {
|
||||
this.host = botOption.host;
|
||||
this.port = botOption.port;
|
||||
|
||||
|
@ -98,22 +135,28 @@ public class Bot {
|
|||
this.bots = bots;
|
||||
|
||||
this.config = config;
|
||||
}
|
||||
this.colorPalette = new ColorPalette(config.colorPalette);
|
||||
|
||||
public void connect () {
|
||||
this.listener = new ListenerManagerPlugin(this);
|
||||
this.tick = new TickPlugin(this);
|
||||
this.chat = new ChatPlugin(this);
|
||||
this.commandSpy = new CommandSpyPlugin(this);
|
||||
this.query = new QueryPlugin(this);
|
||||
this.extrasMessenger = new ExtrasMessengerPlugin(this);
|
||||
this.chomeNSMod = new ChomeNSModIntegrationPlugin(this);
|
||||
this.commandSuggestion = new CommandSuggestionPlugin(this);
|
||||
this.logger = new LoggerPlugin(this);
|
||||
this.position = new PositionPlugin(this);
|
||||
this.serverPluginsManager = new ServerPluginsManagerPlugin(this);
|
||||
this.serverFeatures = new ServerFeaturesPlugin(this);
|
||||
this.selfCare = new SelfCarePlugin(this);
|
||||
this.world = new WorldPlugin(this);
|
||||
this.core = new CorePlugin(this);
|
||||
this.team = new TeamPlugin(this);
|
||||
this.playersDatabase = new PlayersDatabasePlugin(this);
|
||||
this.players = new PlayersPlugin(this);
|
||||
this.tabComplete = new TabCompletePlugin(this);
|
||||
this.commandHandler = new CommandHandlerPlugin(this);
|
||||
this.chatCommandHandler = new ChatCommandHandlerPlugin(this);
|
||||
this.hashing = new HashingPlugin(this);
|
||||
this.bossbar = new BossbarManagerPlugin(this);
|
||||
this.music = new MusicPlayerPlugin(this);
|
||||
this.tps = new TPSPlugin(this);
|
||||
|
@ -123,166 +166,256 @@ public class Bot {
|
|||
this.bruhify = new BruhifyPlugin(this);
|
||||
this.cloop = new CloopPlugin(this);
|
||||
this.exploits = new ExploitsPlugin(this);
|
||||
this.filter = new FilterPlugin(this);
|
||||
this.commandSuggestion = new CommandSuggestionPlugin(this);
|
||||
this.filterManager = new FilterManagerPlugin(this);
|
||||
this.playerFilter = new PlayerFilterPlugin(this);
|
||||
this.mail = new MailPlugin(this);
|
||||
this.packetSniffer = new PacketSnifferPlugin(this);
|
||||
this.voiceChat = new VoiceChatPlugin(this);
|
||||
this.tag = new TagPlugin(this);
|
||||
this.world = new WorldPlugin(this);
|
||||
this.selectorBroadcaster = new BotSelectorBroadcasterPlugin(this);
|
||||
this.auth = new AuthPlugin(this);
|
||||
// this.screenshare = new ScreensharePlugin(this);
|
||||
this.formatChecker = new FormatCheckerPlugin(this);
|
||||
// this.screenshare = new ScreensharePlugin(this);
|
||||
this.clearChatNameAnnouncer = new ClearChatNameAnnouncerPlugin(this);
|
||||
this.whitelist = new WhitelistPlugin(this);
|
||||
this.playersPersistent = new PlayersPersistentDataPlugin(this);
|
||||
this.ipFilter = new IPFilterPlugin(this);
|
||||
this.rainbowArmor = new RainbowArmorPlugin(this);
|
||||
}
|
||||
|
||||
for (Listener listener : listeners) listener.loadedPlugins();
|
||||
|
||||
protected void connect () {
|
||||
reconnect();
|
||||
}
|
||||
|
||||
private void reconnect () {
|
||||
if (session != null) session = null; // does this do nothing?
|
||||
connectAttempts++;
|
||||
|
||||
for (Listener listener : listeners) {
|
||||
listener.connecting();
|
||||
this.listener.dispatch(Listener::onConnecting);
|
||||
|
||||
if (!isTransferring) {
|
||||
username = options.username == null ?
|
||||
RandomStringUtilities.generate(8) :
|
||||
options.username;
|
||||
}
|
||||
|
||||
final String _username = options.username;
|
||||
final ClientNetworkSessionFactory factory = ClientNetworkSessionFactory.factory()
|
||||
.setAddress(host, port)
|
||||
.setProtocol(
|
||||
new MinecraftProtocol(
|
||||
new GameProfile(
|
||||
UUIDUtilities.getOfflineUUID(username),
|
||||
username
|
||||
),
|
||||
null
|
||||
)
|
||||
);
|
||||
|
||||
if (_username == null) username = RandomStringUtilities.generate(8);
|
||||
else username = _username;
|
||||
if (this.session != null) factory.setPacketHandlerExecutor(this.session.getPacketHandlerExecutor());
|
||||
|
||||
Session session = new TcpClientSession(host, port, new MinecraftProtocol(username), null);
|
||||
final ClientSession session = factory.create();
|
||||
|
||||
this.session = session;
|
||||
|
||||
// this replicates the minecraft behavior of not resolving SRV records.
|
||||
// some servers check for this, so that's why i have it here
|
||||
// this is still needed since MinecraftProtocol will use this flag to set the
|
||||
// handshake intention to transfer, it will be set back to false at
|
||||
// login success
|
||||
session.setFlag(BuiltinFlags.CLIENT_TRANSFERRING, isTransferring);
|
||||
|
||||
session.setFlag(MinecraftConstants.FOLLOW_TRANSFERS, false); // we have our own transfer handler
|
||||
|
||||
session.setFlag(BuiltinFlags.ATTEMPT_SRV_RESOLVE, options.resolveSRV);
|
||||
|
||||
session.addListener(new SessionAdapter() {
|
||||
// fard
|
||||
|
||||
@Override
|
||||
public void packetReceived(Session session, Packet packet) {
|
||||
for (SessionListener listener : listeners) {
|
||||
listener.packetReceived(session, packet);
|
||||
}
|
||||
|
||||
if (packet instanceof ClientboundLoginPacket) {
|
||||
for (SessionListener listener : listeners) {
|
||||
loggedIn = true;
|
||||
listener.connected(new ConnectedEvent(session));
|
||||
}
|
||||
|
||||
// this enables all the skin parts (by default they are ALL DISABLED
|
||||
// which is why most bots when they use someone's skin they are just
|
||||
// kinda broken)
|
||||
final List<SkinPart> skinParts = new ArrayList<>();
|
||||
skinParts.add(SkinPart.CAPE);
|
||||
skinParts.add(SkinPart.JACKET);
|
||||
skinParts.add(SkinPart.LEFT_SLEEVE);
|
||||
skinParts.add(SkinPart.RIGHT_SLEEVE);
|
||||
skinParts.add(SkinPart.LEFT_PANTS_LEG);
|
||||
skinParts.add(SkinPart.RIGHT_PANTS_LEG);
|
||||
skinParts.add(SkinPart.HAT);
|
||||
|
||||
// we also set other stuffs here
|
||||
session.send(
|
||||
new ServerboundClientInformationPacket(
|
||||
ComponentUtilities.language.getOrDefault("language.code", "en-us"),
|
||||
16,
|
||||
ChatVisibility.FULL,
|
||||
true,
|
||||
skinParts,
|
||||
HandPreference.RIGHT_HAND,
|
||||
false,
|
||||
true // should this be false lol so only real players are displayed
|
||||
)
|
||||
);
|
||||
|
||||
if (options.creayun) chat.send("/server creative");
|
||||
} else if (packet instanceof ClientboundGameProfilePacket) packetReceived((ClientboundGameProfilePacket) packet);
|
||||
}
|
||||
|
||||
public void packetReceived(ClientboundGameProfilePacket packet) {
|
||||
profile = packet.getProfile();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetSending(PacketSendingEvent packetSendingEvent) {
|
||||
for (SessionListener listener : listeners) {
|
||||
listener.packetSending(packetSendingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetSent(Session session, Packet packet) {
|
||||
for (SessionListener listener : listeners) {
|
||||
listener.packetSent(session, packet);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetError(PacketErrorEvent packetErrorEvent) {
|
||||
for (SessionListener listener : listeners) {
|
||||
listener.packetError(packetErrorEvent);
|
||||
}
|
||||
packetErrorEvent.setSuppress(true); // fix the ohio sus exploit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnecting(DisconnectingEvent disconnectingEvent) {
|
||||
for (SessionListener listener : listeners) {
|
||||
listener.disconnecting(disconnectingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected(DisconnectedEvent disconnectedEvent) {
|
||||
loggedIn = false;
|
||||
|
||||
final Throwable cause = disconnectedEvent.getCause();
|
||||
|
||||
if (printDisconnectedCause && cause != null) cause.printStackTrace();
|
||||
|
||||
// lazy fix #69420
|
||||
if (cause instanceof OutOfMemoryError) System.exit(1);
|
||||
|
||||
int reconnectDelay = options.reconnectDelay;
|
||||
|
||||
final String stringMessage = ComponentUtilities.stringify(disconnectedEvent.getReason());
|
||||
|
||||
if (
|
||||
stringMessage.equals("Wait 5 seconds before connecting, thanks! :)") ||
|
||||
stringMessage.equals("You are logging in too fast, try again later.") ||
|
||||
stringMessage.equals("Connection throttled! Please wait before reconnecting.")
|
||||
) reconnectDelay = 1000 * (5 + 2); // 2 seconds extra delay just in case
|
||||
|
||||
executor.schedule(() -> reconnect(), reconnectDelay, TimeUnit.MILLISECONDS);
|
||||
|
||||
for (SessionListener listener : listeners) {
|
||||
listener.disconnected(disconnectedEvent);
|
||||
}
|
||||
}
|
||||
});
|
||||
session.addListener(this);
|
||||
|
||||
session.connect(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetReceived (final Session session, final Packet packet) {
|
||||
this.listener.dispatch(listener -> listener.packetReceived(session, packet));
|
||||
|
||||
switch (packet) {
|
||||
case final ClientboundLoginPacket t_packet -> packetReceived(t_packet);
|
||||
case final ClientboundLoginFinishedPacket t_packet -> packetReceived(t_packet);
|
||||
case final ClientboundCustomQueryPacket t_packet -> packetReceived(t_packet);
|
||||
case final ClientboundCookieRequestPacket t_packet -> packetReceived(t_packet);
|
||||
case final ClientboundTransferPacket t_packet -> packetReceived(t_packet);
|
||||
case final ClientboundStoreCookiePacket t_packet -> packetReceived(t_packet);
|
||||
case final ClientboundLoginCompressionPacket t_packet -> packetReceived(t_packet);
|
||||
case final ClientboundCustomPayloadPacket t_packet -> packetReceived(t_packet);
|
||||
default -> { }
|
||||
}
|
||||
}
|
||||
|
||||
private void packetReceived (final ClientboundLoginFinishedPacket packet) {
|
||||
profile = packet.getProfile();
|
||||
|
||||
session.setFlag(BuiltinFlags.CLIENT_TRANSFERRING, false);
|
||||
}
|
||||
|
||||
private void packetReceived (final ClientboundLoginPacket ignoredPacket) {
|
||||
loggedIn = true;
|
||||
loginTime = System.currentTimeMillis();
|
||||
connectAttempts = 0;
|
||||
|
||||
this.listener.dispatch(listener -> listener.connected(new ConnectedEvent(session)));
|
||||
|
||||
session.send(ServerboundPlayerLoadedPacket.INSTANCE);
|
||||
}
|
||||
|
||||
private void packetReceived (final ClientboundCustomQueryPacket packet) {
|
||||
session.send(new ServerboundCustomQueryAnswerPacket(packet.getMessageId(), null));
|
||||
}
|
||||
|
||||
private void packetReceived (final ClientboundCustomPayloadPacket packet) {
|
||||
if (!packet.getChannel().asString().equals("minecraft:register")) return;
|
||||
|
||||
session.send(
|
||||
new ServerboundCustomPayloadPacket(
|
||||
Key.key("minecraft", "register"),
|
||||
"\0".getBytes(StandardCharsets.UTF_8)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void packetReceived (final ClientboundCookieRequestPacket packet) {
|
||||
session.send(
|
||||
new ServerboundCookieResponsePacket(
|
||||
packet.getKey(),
|
||||
cookies.get(packet.getKey())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void packetReceived (final ClientboundStoreCookiePacket packet) {
|
||||
cookies.put(packet.getKey(), packet.getPayload());
|
||||
}
|
||||
|
||||
private void packetReceived (final ClientboundTransferPacket ignoredPacket) {
|
||||
this.isTransferring = true;
|
||||
|
||||
session.disconnect(Component.translatable("disconnect.transfer"));
|
||||
}
|
||||
|
||||
// MCProtocolLib devs forgot
|
||||
// "Negative values will disable compression, meaning the packet format should remain in the uncompressed packet format."
|
||||
// https://minecraft.wiki/w/Java_Edition_protocol#Set_Compression
|
||||
|
||||
// they actually implemented this, but at this commit:
|
||||
// https://github.com/GeyserMC/MCProtocolLib/commit/f8460356db2b92fbf7cb506757fe8f87a011a1f7#diff-a9066adbcb6d5503f5edefe3ec95465cf755f1585e02b732a6fa907afe7c7177R67-L103
|
||||
// they removed it, for some reason
|
||||
private void packetReceived (final ClientboundLoginCompressionPacket packet) {
|
||||
if (packet.getThreshold() < 0) {
|
||||
session.setCompression(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetSending (final PacketSendingEvent packetSendingEvent) {
|
||||
this.listener.dispatch(listener -> listener.packetSending(packetSendingEvent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetSent (final Session session, final Packet packet) {
|
||||
this.listener.dispatch(listener -> listener.packetSent(session, packet));
|
||||
|
||||
if (packet instanceof final ServerboundLoginAcknowledgedPacket t_packet) packetSent(t_packet);
|
||||
}
|
||||
|
||||
private void packetSent (final ServerboundLoginAcknowledgedPacket ignoredPacket) {
|
||||
// doesn't work without executing
|
||||
session.getPacketHandlerExecutor().execute(() -> {
|
||||
// for voicechat
|
||||
session.send(new ServerboundCustomPayloadPacket(
|
||||
Key.key("minecraft:brand"),
|
||||
"\u0006fabric".getBytes(StandardCharsets.UTF_8)
|
||||
));
|
||||
|
||||
// this enables all the skin parts (by default they are ALL DISABLED
|
||||
// which is why most bots when they use someone's skin they are just
|
||||
// kinda broken)
|
||||
final List<SkinPart> skinParts = new ArrayList<>(Arrays.asList(SkinPart.VALUES));
|
||||
|
||||
// we also set other stuffs here
|
||||
session.send(
|
||||
new ServerboundClientInformationPacket(
|
||||
ComponentUtilities.LANGUAGE.getOrDefault("language.code", "en_us"),
|
||||
16,
|
||||
ChatVisibility.FULL,
|
||||
true,
|
||||
skinParts,
|
||||
HandPreference.RIGHT_HAND,
|
||||
false,
|
||||
false,
|
||||
ParticleStatus.ALL
|
||||
)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void packetError (final PacketErrorEvent packetErrorEvent) {
|
||||
this.listener.dispatch(listener -> listener.packetError(packetErrorEvent));
|
||||
packetErrorEvent.setSuppress(true); // fixes the ohio sus exploit
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnecting (final DisconnectingEvent disconnectingEvent) {
|
||||
this.listener.dispatch(listener -> listener.disconnecting(disconnectingEvent));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnected (final DisconnectedEvent disconnectedEvent) {
|
||||
loggedIn = false;
|
||||
|
||||
final Throwable cause = disconnectedEvent.getCause();
|
||||
|
||||
if (printDisconnectedCause && cause != null) logger.error(cause);
|
||||
|
||||
if (Main.stopping) return;
|
||||
|
||||
if (!isTransferring) cookies.clear();
|
||||
|
||||
if (isTransferring) {
|
||||
// for now, it's going to transfer to the same server instead of
|
||||
// other servers
|
||||
|
||||
reconnect(); // instantly reconnect
|
||||
|
||||
isTransferring = false;
|
||||
} else {
|
||||
final String stringMessage = ComponentUtilities.stringify(disconnectedEvent.getReason());
|
||||
|
||||
final long reconnectDelay;
|
||||
|
||||
if (NEEDS_DELAY_DISCONNECT_REASON.contains(stringMessage))
|
||||
reconnectDelay = TimeUnit.SECONDS.toMillis(5);
|
||||
else
|
||||
reconnectDelay = options.reconnectDelay;
|
||||
|
||||
executor.schedule(this::reconnect, reconnectDelay, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
this.listener.dispatch(listener -> listener.disconnected(disconnectedEvent));
|
||||
}
|
||||
|
||||
public String getServerString () { return getServerString(false); }
|
||||
|
||||
public String getServerString (final boolean bypassHidden) {
|
||||
return options.hidden && !bypassHidden ?
|
||||
options.serverName :
|
||||
host + ":" + port;
|
||||
}
|
||||
|
||||
public void stop () {
|
||||
session.disconnect("Received stop signal");
|
||||
Main.bots.remove(this);
|
||||
}
|
||||
|
||||
public void addListener (Listener listener) {
|
||||
listeners.add(listener);
|
||||
}
|
||||
|
||||
public static class Listener extends SessionAdapter {
|
||||
public void connecting () {}
|
||||
public void loadedPlugins () {}
|
||||
@Override
|
||||
public String toString () {
|
||||
return "Bot{" +
|
||||
"host='" + host + '\'' +
|
||||
", port=" + port +
|
||||
", username='" + username + '\'' +
|
||||
", loggedIn=" + loggedIn +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
package me.chayapak1.chomens_bot;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class Configuration {
|
||||
public List<String> prefixes;
|
||||
|
@ -11,15 +9,15 @@ public class Configuration {
|
|||
|
||||
public String consoleCommandPrefix;
|
||||
|
||||
public Keys keys = new Keys();
|
||||
|
||||
public InternetCheck internetCheck = new InternetCheck();
|
||||
|
||||
public Backup backup = new Backup();
|
||||
|
||||
public Database database = new Database();
|
||||
|
||||
public ChomeNSMod chomeNSMod = new ChomeNSMod();
|
||||
|
||||
public String weatherApiKey;
|
||||
|
||||
public String bossBarNamespace = "chomens_bot";
|
||||
public String namespace = "chomens_bot";
|
||||
|
||||
public Core core = new Core();
|
||||
public Discord discord = new Discord();
|
||||
|
@ -29,61 +27,55 @@ public class Configuration {
|
|||
public Eval eval = new Eval();
|
||||
|
||||
public ColorPalette colorPalette = new ColorPalette();
|
||||
|
||||
|
||||
public String ownerName = "chayapak"; // mabe mabe
|
||||
|
||||
public ImposterFormatChecker imposterFormatChecker = new ImposterFormatChecker();
|
||||
public String consoleChatFormat = "{\"translate\":\"chat.type.text\",\"with\":[\"OWNER_NAME\",\"MESSAGE\"]}";
|
||||
|
||||
public OwnerAuthentication ownerAuthentication = new OwnerAuthentication();
|
||||
|
||||
|
||||
public boolean announceClearChatUsername = false;
|
||||
|
||||
public boolean rainbowArmor = true;
|
||||
|
||||
public List<String> trusted = new ArrayList<>();
|
||||
public SelfCare selfCare = new SelfCare();
|
||||
|
||||
public BotOption[] bots = new BotOption[]{};
|
||||
|
||||
public static class ImposterFormatChecker {
|
||||
public boolean enabled = false;
|
||||
public String key;
|
||||
}
|
||||
public BotOption[] bots = new BotOption[] {};
|
||||
|
||||
public static class OwnerAuthentication {
|
||||
public boolean enabled = false;
|
||||
public String key = "";
|
||||
public int timeout = 6000;
|
||||
}
|
||||
|
||||
public static class InternetCheck {
|
||||
public boolean enabled = true;
|
||||
public String address = "https://sus.red";
|
||||
public int timeout = 10;
|
||||
}
|
||||
|
||||
public static class Backup {
|
||||
public boolean enabled = false;
|
||||
public String address = "http://fard.sex/check";
|
||||
public int interval = 1000;
|
||||
public int failTimes = 2;
|
||||
}
|
||||
|
||||
public static class Keys {
|
||||
public String normalKey;
|
||||
public String ownerKey;
|
||||
public static class Database {
|
||||
public boolean enabled = false;
|
||||
public String address = "localhost";
|
||||
public String username = "chomens_bot";
|
||||
public String password = "123456";
|
||||
}
|
||||
|
||||
public static class ChomeNSMod {
|
||||
public boolean enabled = false;
|
||||
public String password = "123456";
|
||||
public List<String> players = new ArrayList<>();
|
||||
}
|
||||
|
||||
public static class Core {
|
||||
public Position start = new Position();
|
||||
public Position end = new Position();
|
||||
public int refillInterval = (60 * 5) * 1000; // 5 minutes
|
||||
public String customName = "{\"text\":\"@\"}";
|
||||
}
|
||||
|
||||
public static class Position {
|
||||
public int x = 0;
|
||||
public int y = 0;
|
||||
public int z = 0;
|
||||
}
|
||||
|
||||
public static class ColorPalette {
|
||||
public String primary = "yellow";
|
||||
public String secondary = "gold";
|
||||
public String defaultColor = "white";
|
||||
public String defaultColor = "gray";
|
||||
public String username = "gold";
|
||||
public String uuid = "aqua";
|
||||
public String string = "aqua";
|
||||
|
@ -92,25 +84,31 @@ public class Configuration {
|
|||
}
|
||||
|
||||
public static class Discord {
|
||||
public boolean enabled = true;
|
||||
public boolean enabled = false;
|
||||
public String prefix = "default!";
|
||||
public String serverId;
|
||||
public boolean enableDiscordHashing = true;
|
||||
public String token;
|
||||
public Map<String, String> servers = new HashMap<>();
|
||||
public EmbedColors embedColors = new EmbedColors();
|
||||
public String trustedRoleName = "Trusted";
|
||||
public String adminRoleName = "Admin";
|
||||
public String ownerRoleName = "Owner";
|
||||
public String statusMessage = "Oh hi!";
|
||||
public String inviteLink = "https://discord.gg/xdgCkUyaA4";
|
||||
|
||||
public static class EmbedColors {
|
||||
public String normal = "#FFFF00";
|
||||
public String error = "#FF0000";
|
||||
}
|
||||
}
|
||||
|
||||
public static class IRC {
|
||||
public boolean enabled = true;
|
||||
public boolean enabled = false;
|
||||
public String prefix = "!";
|
||||
public String host;
|
||||
public int port;
|
||||
public String name = "chomens-bot";
|
||||
public String password = "";
|
||||
public Map<String, String> servers = new HashMap<>();
|
||||
}
|
||||
|
||||
public static class Music {
|
||||
|
@ -122,36 +120,23 @@ public class Configuration {
|
|||
}
|
||||
}
|
||||
|
||||
public static class EmbedColors {
|
||||
public String normal = "#FFFF00";
|
||||
public String error = "#FF0000";
|
||||
}
|
||||
|
||||
public static class Eval {
|
||||
public String address = "ws://localhost:3069";
|
||||
}
|
||||
|
||||
public static class SelfCare {
|
||||
public int delay = 225;
|
||||
|
||||
public boolean op = true;
|
||||
public boolean gamemode = true;
|
||||
public boolean endCredits = true;
|
||||
public boolean respawn = true;
|
||||
|
||||
public boolean vanish = true;
|
||||
public boolean nickname = true;
|
||||
public boolean god = true;
|
||||
public boolean socialspy = true;
|
||||
public boolean mute = true;
|
||||
|
||||
public boolean cspy = true;
|
||||
|
||||
public Icu icu = new Icu();
|
||||
|
||||
public static class Icu {
|
||||
public boolean enabled = true;
|
||||
public int positionPacketsPerSecond = 10;
|
||||
}
|
||||
|
||||
public Prefix prefix = new Prefix();
|
||||
|
||||
public static class Prefix {
|
||||
|
@ -159,6 +144,8 @@ public class Configuration {
|
|||
public String prefix = "&8[&eChomeNS Bot&8]";
|
||||
}
|
||||
|
||||
public boolean icu = true;
|
||||
|
||||
public boolean username = true;
|
||||
}
|
||||
|
||||
|
@ -166,18 +153,40 @@ public class Configuration {
|
|||
public String host;
|
||||
public int port;
|
||||
public String username;
|
||||
public boolean creayun = false;
|
||||
public String serverName;
|
||||
public String discordChannelId;
|
||||
public String ircChannel;
|
||||
public boolean hidden = false;
|
||||
public boolean useCore = true;
|
||||
public boolean useCorePlaceBlock = false;
|
||||
public boolean useChat = false;
|
||||
public boolean coreCommandSpy = false;
|
||||
public boolean useSNBTComponents = true;
|
||||
public boolean coreCommandSpy = true;
|
||||
public boolean logConnectionStatusMessages = true;
|
||||
public boolean resolveSRV = true;
|
||||
public int reconnectDelay = 2000;
|
||||
public boolean removeNamespaces = false;
|
||||
public int chatQueueDelay = 125;
|
||||
public EssentialsMessages essentialsMessages = new EssentialsMessages();
|
||||
public CoreRateLimit coreRateLimit = new CoreRateLimit();
|
||||
|
||||
public static class EssentialsMessages {
|
||||
public String vanishEnable1 = "Vanish for %s: enabled";
|
||||
public String vanishEnable2 = "You are now completely invisible to normal users, and hidden from in-game commands.";
|
||||
public String vanishDisable = "Vanish for %s: disabled";
|
||||
|
||||
public String nickNameRemove = "You no longer have a nickname.";
|
||||
public String nickNameSet = "Your nickname is now ";
|
||||
|
||||
public String godModeEnable = "God mode enabled.";
|
||||
public String godModeDisable = "God mode disabled.";
|
||||
|
||||
public String socialSpyEnable = "SocialSpy for %s: enabled";
|
||||
public String socialSpyDisable = "SocialSpy for %s: disabled";
|
||||
|
||||
public String muted = "You have been muted";
|
||||
public String unmuted = "You have been unmuted.";
|
||||
}
|
||||
|
||||
public static class CoreRateLimit {
|
||||
public int limit = 0;
|
||||
public int reset = 0;
|
||||
|
|
|
@ -1,41 +1,38 @@
|
|||
package me.chayapak1.chomens_bot;
|
||||
|
||||
import com.google.common.util.concurrent.ThreadFactoryBuilder;
|
||||
import me.chayapak1.chomens_bot.plugins.ConsolePlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.DiscordPlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.IRCPlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.LoggerPlugin;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import me.chayapak1.chomens_bot.plugins.*;
|
||||
import me.chayapak1.chomens_bot.util.*;
|
||||
import net.dv8tion.jda.api.requests.restaction.MessageCreateAction;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.yaml.snakeyaml.LoaderOptions;
|
||||
import org.yaml.snakeyaml.Yaml;
|
||||
import org.yaml.snakeyaml.constructor.Constructor;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.UnknownHostException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class Main {
|
||||
public static final List<Bot> bots = new ArrayList<>();
|
||||
public static final Path stopReasonFilePath = Path.of("shutdown_reason.txt");
|
||||
|
||||
public static final ExecutorService executorService = Executors.newFixedThreadPool(
|
||||
Runtime.getRuntime().availableProcessors(),
|
||||
public static final List<Bot> bots = new ObjectArrayList<>();
|
||||
|
||||
public static final ExecutorService EXECUTOR_SERVICE = Executors.newFixedThreadPool(
|
||||
Math.max(1, Runtime.getRuntime().availableProcessors() / 2),
|
||||
new ThreadFactoryBuilder().setNameFormat("ExecutorService #%d").build()
|
||||
);
|
||||
public static final ScheduledExecutorService executor = Executors.newScheduledThreadPool(
|
||||
Runtime.getRuntime().availableProcessors(),
|
||||
public static final ScheduledExecutorService EXECUTOR = Executors.newScheduledThreadPool(
|
||||
Math.max(1, Runtime.getRuntime().availableProcessors() / 2),
|
||||
new ThreadFactoryBuilder().setNameFormat("ScheduledExecutorService #%d").build()
|
||||
);
|
||||
|
||||
|
@ -43,13 +40,57 @@ public class Main {
|
|||
|
||||
private static boolean alreadyStarted = false;
|
||||
|
||||
private static boolean stopping = false;
|
||||
public static boolean stopping = false;
|
||||
|
||||
private static final List<Thread> alreadyAddedThreads = new ArrayList<>();
|
||||
private static int backupFailTimes = 0;
|
||||
|
||||
private static DiscordPlugin discord;
|
||||
public static ConsolePlugin console;
|
||||
public static DatabasePlugin database;
|
||||
public static DiscordPlugin discord;
|
||||
public static IRCPlugin irc;
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
public static void main (final String[] args) throws IOException {
|
||||
Locale.setDefault(Locale.ROOT);
|
||||
|
||||
loadConfig();
|
||||
|
||||
final Thread shutdownThread = new Thread(Main::handleShutdown, "ChomeNS Bot Shutdown Thread");
|
||||
Runtime.getRuntime().addShutdownHook(shutdownThread);
|
||||
|
||||
if (!config.backup.enabled) {
|
||||
initializeBots();
|
||||
} else {
|
||||
EXECUTOR.scheduleAtFixedRate(() -> {
|
||||
boolean reachable;
|
||||
|
||||
try {
|
||||
HttpUtilities.getRequest(new URI(config.backup.address).toURL());
|
||||
|
||||
reachable = true;
|
||||
} catch (final Exception e) {
|
||||
reachable = false;
|
||||
}
|
||||
|
||||
if (!reachable && !alreadyStarted) {
|
||||
backupFailTimes++;
|
||||
|
||||
if (backupFailTimes > config.backup.failTimes) {
|
||||
LoggerUtilities.log("Main instance is down! Starting backup instance");
|
||||
|
||||
initializeBots();
|
||||
}
|
||||
} else if (reachable && alreadyStarted) {
|
||||
LoggerUtilities.log("Main instance is back up! Now stopping");
|
||||
|
||||
// no need to reset backupFailTimes because we are stopping anyway
|
||||
|
||||
stop(0);
|
||||
}
|
||||
}, 0, config.backup.interval, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
private static void loadConfig () throws IOException {
|
||||
final Path configPath = Path.of("config.yml");
|
||||
|
||||
final Constructor constructor = new Constructor(Configuration.class, new LoaderOptions());
|
||||
|
@ -57,151 +98,97 @@ public class Main {
|
|||
|
||||
if (!Files.exists(configPath)) {
|
||||
// creates config file from default-config.yml
|
||||
InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("default-config.yml");
|
||||
final InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream("default-config.yml");
|
||||
|
||||
if (is == null) System.exit(1);
|
||||
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(is));
|
||||
final StringBuilder stringBuilder = new StringBuilder();
|
||||
while (reader.ready()) {
|
||||
char character = (char) reader.read();
|
||||
final char character = (char) reader.read();
|
||||
stringBuilder.append(character);
|
||||
}
|
||||
String defaultConfig = stringBuilder.toString();
|
||||
final String defaultConfig = stringBuilder.toString();
|
||||
|
||||
// writes it
|
||||
BufferedWriter configWriter = Files.newBufferedWriter(configPath);
|
||||
final BufferedWriter configWriter = Files.newBufferedWriter(configPath);
|
||||
configWriter.write(defaultConfig);
|
||||
configWriter.close();
|
||||
|
||||
LoggerUtilities.info("config.yml file not found, so the default one was created");
|
||||
LoggerUtilities.log("config.yml file was not found, so the default one was created. Please modify it to your needs.");
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
InputStream opt = Files.newInputStream(configPath);
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(opt));
|
||||
final InputStream opt = Files.newInputStream(configPath);
|
||||
final BufferedReader reader = new BufferedReader(new InputStreamReader(opt));
|
||||
|
||||
config = yaml.load(reader);
|
||||
|
||||
executor.scheduleAtFixedRate(() -> {
|
||||
try {
|
||||
checkInternet();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, 0, 1, TimeUnit.MINUTES);
|
||||
|
||||
executor.scheduleAtFixedRate(() -> {
|
||||
final Set<Thread> threads = Thread.getAllStackTraces().keySet();
|
||||
|
||||
for (Thread thread : threads) {
|
||||
final Thread.UncaughtExceptionHandler oldHandler = thread.getUncaughtExceptionHandler();
|
||||
|
||||
thread.setUncaughtExceptionHandler((_thread, throwable) -> {
|
||||
if (!alreadyAddedThreads.contains(thread) && throwable instanceof OutOfMemoryError) System.exit(1);
|
||||
|
||||
alreadyAddedThreads.add(thread);
|
||||
|
||||
oldHandler.uncaughtException(_thread, throwable);
|
||||
});
|
||||
}
|
||||
}, 0, 30, TimeUnit.SECONDS);
|
||||
|
||||
if (!config.backup.enabled) {
|
||||
initializeBots();
|
||||
return;
|
||||
}
|
||||
|
||||
executor.scheduleAtFixedRate(() -> {
|
||||
boolean reachable;
|
||||
|
||||
try {
|
||||
HttpUtilities.getRequest(new URL(config.backup.address));
|
||||
|
||||
reachable = true;
|
||||
} catch (Exception e) {
|
||||
reachable = false;
|
||||
}
|
||||
|
||||
if (!reachable && !alreadyStarted) {
|
||||
LoggerUtilities.info("Main instance is down! Starting backup instance");
|
||||
|
||||
initializeBots();
|
||||
} else if (reachable && alreadyStarted) {
|
||||
System.exit(1);
|
||||
}
|
||||
}, 0, 1, TimeUnit.MINUTES);
|
||||
}
|
||||
|
||||
public static void initializeBots() {
|
||||
private static void initializeBots () {
|
||||
alreadyStarted = true;
|
||||
|
||||
try {
|
||||
if (config.database.enabled) database = new DatabasePlugin(config);
|
||||
HashingUtilities.init();
|
||||
|
||||
final Configuration.BotOption[] botsOptions = config.bots;
|
||||
|
||||
for (Configuration.BotOption botOption : botsOptions) {
|
||||
for (final Configuration.BotOption botOption : botsOptions) {
|
||||
final Bot bot = new Bot(botOption, bots, config);
|
||||
bots.add(bot);
|
||||
}
|
||||
|
||||
// initialize util classes and plugins
|
||||
PersistentDataUtilities.init();
|
||||
ComponentUtilities.init();
|
||||
|
||||
new ConsolePlugin();
|
||||
LoggerPlugin.init();
|
||||
console = new ConsolePlugin(config);
|
||||
if (config.discord.enabled) discord = new DiscordPlugin(config);
|
||||
if (config.irc.enabled) new IRCPlugin(config);
|
||||
if (config.irc.enabled) irc = new IRCPlugin(config);
|
||||
EvalPlugin.connect(config.eval.address);
|
||||
|
||||
LoggerUtilities.info("Initialized all bots. Now connecting");
|
||||
LoggerUtilities.log(I18nUtilities.get("initialized"));
|
||||
|
||||
for (Bot bot : bots) bot.connect();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
for (final Bot bot : bots) bot.connect();
|
||||
} catch (final Exception e) {
|
||||
LoggerUtilities.error(e);
|
||||
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkInternet () throws IOException {
|
||||
if (!config.internetCheck.enabled) return;
|
||||
private static void handleShutdown () {
|
||||
String reason = null;
|
||||
|
||||
boolean reachable = false;
|
||||
|
||||
try {
|
||||
final URL url = new URL(config.internetCheck.address);
|
||||
|
||||
final URLConnection connection = url.openConnection();
|
||||
|
||||
connection.connect();
|
||||
|
||||
reachable = true;
|
||||
} catch (UnknownHostException ignored) {}
|
||||
|
||||
if (!reachable) {
|
||||
LoggerUtilities.error("No internet, exiting");
|
||||
|
||||
System.exit(1);
|
||||
if (Files.exists(stopReasonFilePath)) {
|
||||
try {
|
||||
reason = new String(Files.readAllBytes(stopReasonFilePath)).trim();
|
||||
} catch (final IOException ignored) { }
|
||||
}
|
||||
|
||||
stop(0, reason, false);
|
||||
}
|
||||
|
||||
// most of these are stolen from HBot
|
||||
public static void stop () {
|
||||
public static void stop (final int exitCode) { stop(exitCode, null, null, true); }
|
||||
|
||||
public static void stop (final int exitCode, final String reason) { stop(exitCode, reason, null, true); }
|
||||
|
||||
public static void stop (final int exitCode, final String reason, final String type) { stop(exitCode, reason, type, true); }
|
||||
|
||||
public static void stop (final int exitCode, final String reason, final boolean callSystemExit) { stop(exitCode, reason, null, callSystemExit); }
|
||||
|
||||
public static void stop (final int exitCode, final String reason, final String type, final boolean callSystemExit) {
|
||||
if (stopping) return;
|
||||
else stopping = true;
|
||||
|
||||
stopping = true;
|
||||
final String stoppingMessage = String.format(
|
||||
I18nUtilities.get("info.stopping.generic"),
|
||||
type != null ? type : I18nUtilities.get("info.stopping"),
|
||||
reason != null ? reason : I18nUtilities.get("info.no_reason")
|
||||
);
|
||||
|
||||
executor.shutdown();
|
||||
LoggerUtilities.log(stoppingMessage);
|
||||
|
||||
PersistentDataUtilities.stop();
|
||||
|
||||
executorService.shutdown();
|
||||
|
||||
try {
|
||||
final boolean ignoredExecutorDone = executor.awaitTermination(5, TimeUnit.SECONDS);
|
||||
final boolean ignoredExecutorServiceDone = executorService.awaitTermination(5, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ignored) {}
|
||||
|
||||
ArrayList<Bot> copiedList;
|
||||
final ArrayList<Bot> copiedList;
|
||||
synchronized (bots) {
|
||||
copiedList = new ArrayList<>(bots);
|
||||
}
|
||||
|
@ -209,42 +196,48 @@ public class Main {
|
|||
final boolean ircEnabled = config.irc.enabled;
|
||||
final boolean discordEnabled = config.discord.enabled;
|
||||
|
||||
if (ircEnabled) irc.quit(stoppingMessage);
|
||||
|
||||
final boolean[] stoppedDiscord = new boolean[copiedList.size()];
|
||||
|
||||
int botIndex = 0;
|
||||
for (Bot bot : copiedList) {
|
||||
final AtomicInteger botIndex = new AtomicInteger();
|
||||
for (final Bot bot : copiedList) {
|
||||
try {
|
||||
if (discordEnabled) {
|
||||
final String channelId = bot.discord.servers.get(bot.host + ":" + bot.port);
|
||||
final String channelId = bot.options.discordChannelId;
|
||||
|
||||
final MessageCreateAction messageAction = bot.discord.sendMessageInstantly("Stopping..", channelId, false);
|
||||
final MessageCreateAction messageAction = Main.discord.sendMessageInstantly(stoppingMessage, channelId, false);
|
||||
|
||||
final int currentIndex = botIndex.get();
|
||||
|
||||
final int finalBotIndex = botIndex;
|
||||
messageAction.queue(
|
||||
(message) -> stoppedDiscord[finalBotIndex] = true,
|
||||
(error) -> stoppedDiscord[finalBotIndex] = true // should i also set this to true on fail?
|
||||
(message) -> stoppedDiscord[currentIndex] = true,
|
||||
(error) -> stoppedDiscord[currentIndex] = true // should i also set this to true on fail?
|
||||
);
|
||||
}
|
||||
|
||||
if (ircEnabled) bot.irc.quit("Stopping..");
|
||||
|
||||
bot.stop();
|
||||
} catch (Exception ignored) {}
|
||||
} catch (final Exception ignored) { }
|
||||
|
||||
botIndex++;
|
||||
botIndex.getAndIncrement();
|
||||
}
|
||||
|
||||
if (discord.jda != null) discord.jda.shutdown();
|
||||
|
||||
if (discordEnabled) {
|
||||
for (int i = 0; i < 150; i++) {
|
||||
try {
|
||||
if (!ArrayUtilities.isAllTrue(stoppedDiscord)) Thread.sleep(50);
|
||||
else break;
|
||||
} catch (InterruptedException ignored) {}
|
||||
} catch (final InterruptedException ignored) { }
|
||||
}
|
||||
|
||||
if (discord != null && discord.jda != null) discord.jda.shutdown();
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
EXECUTOR.shutdown();
|
||||
EXECUTOR_SERVICE.shutdown();
|
||||
FileLoggerUtilities.stop();
|
||||
if (database != null) database.stop();
|
||||
|
||||
if (callSystemExit) System.exit(exitCode);
|
||||
}
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.chatParsers;
|
||||
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatParser;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.chat.PlayerMessage;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class CreayunChatParser implements ChatParser {
|
||||
private final Bot bot;
|
||||
|
||||
// is parsing creayun chat using regex a good idea?
|
||||
// mabe mabe mabe
|
||||
// it doesn't use like translation or anything
|
||||
private static final Pattern PATTERN = Pattern.compile("([^ ]*) » (.*)");
|
||||
|
||||
public CreayunChatParser (Bot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerMessage parse (Component message) {
|
||||
final String stringified = ComponentUtilities.stringify(message);
|
||||
|
||||
if (!bot.options.creayun) return null;
|
||||
|
||||
final Matcher matcher = PATTERN.matcher(stringified);
|
||||
|
||||
if (matcher.find()) {
|
||||
final String displayName = matcher.group(1);
|
||||
final String contents = matcher.group(2);
|
||||
|
||||
PlayerEntry sender = bot.players.getEntry(displayName);
|
||||
if (sender == null) sender = new PlayerEntry(new GameProfile(UUIDUtilities.getOfflineUUID(displayName), displayName), GameMode.SURVIVAL, 0, Component.text(displayName), 0L, null, new byte[0], true);
|
||||
|
||||
return new PlayerMessage(sender, Component.text(displayName), Component.text(contents));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -1,38 +1,37 @@
|
|||
package me.chayapak1.chomens_bot.chatParsers;
|
||||
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatParser;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.chat.PlayerMessage;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TextComponent;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KaboomChatParser implements ChatParser {
|
||||
private final Bot bot;
|
||||
|
||||
public KaboomChatParser (Bot bot) {
|
||||
public KaboomChatParser (final Bot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerMessage parse (Component message) {
|
||||
public PlayerMessage parse (final Component message) {
|
||||
if (message instanceof TextComponent) return parse((TextComponent) message);
|
||||
return null;
|
||||
}
|
||||
|
||||
public PlayerMessage parse (TextComponent message) {
|
||||
List<Component> children = message.children();
|
||||
public PlayerMessage parse (final TextComponent message) {
|
||||
final List<Component> children = message.children();
|
||||
|
||||
if (!message.content().isEmpty() || !message.style().isEmpty() || children.size() < 3) return null;
|
||||
|
||||
final Component prefix = children.get(0);
|
||||
final Component prefix = children.getFirst();
|
||||
Component displayName = Component.empty();
|
||||
Component contents = Component.empty();
|
||||
|
||||
|
@ -45,17 +44,29 @@ public class KaboomChatParser implements ChatParser {
|
|||
return null;
|
||||
}
|
||||
|
||||
// final String stringifiedDisplayName = ComponentUtilities.stringify(displayName);
|
||||
final String stringifiedDisplayName = ComponentUtilities.stringify(displayName);
|
||||
|
||||
PlayerEntry sender = bot.players.getEntry(Component.empty().append(prefix).append(displayName));
|
||||
if (sender == null) sender = bot.players.getEntry(prefix.append(displayName)); // old
|
||||
// if (sender == null) sender = new PlayerEntry(new GameProfile(UUIDUtilities.getOfflineUUID(stringifiedDisplayName), stringifiedDisplayName), GameMode.SURVIVAL, 0, displayName, 0L, null, new byte[0], true); // new and currently using
|
||||
if (sender == null) return null;
|
||||
|
||||
if (sender == null) sender = bot.players.getEntry(prefix.append(displayName));
|
||||
if (sender == null) sender = new PlayerEntry(
|
||||
new GameProfile(
|
||||
UUIDUtilities.getOfflineUUID(stringifiedDisplayName),
|
||||
stringifiedDisplayName
|
||||
),
|
||||
GameMode.SURVIVAL,
|
||||
0,
|
||||
displayName,
|
||||
0L,
|
||||
null,
|
||||
new byte[0],
|
||||
true
|
||||
);
|
||||
|
||||
return new PlayerMessage(sender, displayName, contents);
|
||||
}
|
||||
|
||||
private boolean isSeperatorAt (List<Component> children, int start) {
|
||||
private boolean isSeperatorAt (final List<Component> children, final int start) {
|
||||
return (
|
||||
children.get(start).equals(Component.text(":")) ||
|
||||
children.get(start).equals(Component.text("§f:"))
|
||||
|
|
|
@ -1,52 +1,53 @@
|
|||
package me.chayapak1.chomens_bot.chatParsers;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectList;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatParser;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.chat.PlayerMessage;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.TranslationArgument;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
public class MinecraftChatParser implements ChatParser {
|
||||
private final Bot bot;
|
||||
|
||||
private static final List<String> keys = new ArrayList<>();
|
||||
static {
|
||||
keys.add("chat.type.text");
|
||||
keys.add("chat.type.announcement");
|
||||
keys.add("commands.message.display.incoming");
|
||||
keys.add("chat.type.team.text");
|
||||
keys.add("chat.type.emote");
|
||||
}
|
||||
private static final List<String> keys = ObjectList.of(
|
||||
"chat.type.text",
|
||||
"chat.type.announcement",
|
||||
"commands.message.display.incoming",
|
||||
"chat.type.team.text",
|
||||
"chat.type.emote"
|
||||
);
|
||||
|
||||
public MinecraftChatParser (Bot bot) {
|
||||
public MinecraftChatParser (final Bot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerMessage parse (Component message) {
|
||||
public PlayerMessage parse (final Component message) {
|
||||
if (message instanceof TranslatableComponent) return parse((TranslatableComponent) message);
|
||||
return null;
|
||||
}
|
||||
|
||||
public PlayerMessage parse (TranslatableComponent message) {
|
||||
public PlayerMessage parse (final TranslatableComponent message) {
|
||||
final List<TranslationArgument> args = message.arguments();
|
||||
final String key = message.key();
|
||||
if (args.size() < 2 || !keys.contains(key)) return null;
|
||||
|
||||
final Component senderComponent = args.get(0).asComponent();
|
||||
final Component senderComponent = args.getFirst().asComponent();
|
||||
final Component contents = args.get(1).asComponent();
|
||||
|
||||
PlayerEntry sender;
|
||||
final PlayerEntry sender;
|
||||
|
||||
final HoverEvent<?> hoverEvent = senderComponent.hoverEvent();
|
||||
if (hoverEvent != null && hoverEvent.action().equals(HoverEvent.Action.SHOW_ENTITY)) {
|
||||
HoverEvent.ShowEntity entityInfo = (HoverEvent.ShowEntity) hoverEvent.value();
|
||||
final HoverEvent.ShowEntity entityInfo = (HoverEvent.ShowEntity) hoverEvent.value();
|
||||
final UUID senderUUID = entityInfo.id();
|
||||
sender = bot.players.getEntry(senderUUID);
|
||||
} else {
|
||||
|
|
|
@ -2,8 +2,8 @@ package me.chayapak1.chomens_bot.chatParsers;
|
|||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatParser;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.chat.PlayerMessage;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
|
@ -17,28 +17,29 @@ import java.util.UUID;
|
|||
public class U203aChatParser implements ChatParser {
|
||||
private final Bot bot;
|
||||
|
||||
public U203aChatParser(Bot bot) {
|
||||
public U203aChatParser (final Bot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PlayerMessage parse (Component message) {
|
||||
public PlayerMessage parse (final Component message) {
|
||||
if (message instanceof TranslatableComponent) return parse((TranslatableComponent) message);
|
||||
return null;
|
||||
}
|
||||
|
||||
// very similar to MinecraftChatParser
|
||||
public PlayerMessage parse (TranslatableComponent message) {
|
||||
public PlayerMessage parse (final TranslatableComponent message) {
|
||||
final List<TranslationArgument> args = message.arguments();
|
||||
if (args.size() < 3 || (!message.key().equals("[%s] %s › %s") && !message.key().equals("%s %s › %s"))) return null;
|
||||
if (args.size() < 3 || (!message.key().equals("[%s] %s › %s") && !message.key().equals("%s %s › %s")))
|
||||
return null;
|
||||
|
||||
final Component senderComponent = args.get(1).asComponent();
|
||||
final Component contents = args.get(2).asComponent();
|
||||
|
||||
PlayerEntry sender;
|
||||
final PlayerEntry sender;
|
||||
final HoverEvent<?> hoverEvent = senderComponent.hoverEvent();
|
||||
if (hoverEvent != null && hoverEvent.action().equals(HoverEvent.Action.SHOW_ENTITY)) {
|
||||
HoverEvent.ShowEntity entityInfo = (HoverEvent.ShowEntity) hoverEvent.value();
|
||||
final HoverEvent.ShowEntity entityInfo = (HoverEvent.ShowEntity) hoverEvent.value();
|
||||
final UUID senderUUID = entityInfo.id();
|
||||
sender = bot.players.getEntry(senderUUID);
|
||||
} else {
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.SecretKeyFactory;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.PBEKeySpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.security.SecureRandom;
|
||||
import java.security.spec.KeySpec;
|
||||
|
||||
// inspired from smp encryption plugin
|
||||
// Author: ChatGPT
|
||||
public class Encryptor {
|
||||
private static final SecureRandom RANDOM = new SecureRandom();
|
||||
|
||||
private static final int SALT_LENGTH = 16;
|
||||
private static final int IV_LENGTH = 16;
|
||||
private static final int ITERATIONS = 65536;
|
||||
private static final int KEY_LENGTH = 256;
|
||||
|
||||
public static byte[] encrypt (final byte[] data, final String password) throws Exception {
|
||||
final byte[] salt = generateRandomBytes(SALT_LENGTH);
|
||||
final SecretKey key = deriveKey(password, salt);
|
||||
|
||||
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
final byte[] iv = generateRandomBytes(IV_LENGTH);
|
||||
final IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
|
||||
|
||||
final byte[] encrypted = cipher.doFinal(data);
|
||||
|
||||
final byte[] combined = new byte[salt.length + iv.length + encrypted.length];
|
||||
System.arraycopy(salt, 0, combined, 0, salt.length);
|
||||
System.arraycopy(iv, 0, combined, salt.length, iv.length);
|
||||
System.arraycopy(encrypted, 0, combined, salt.length + iv.length, encrypted.length);
|
||||
|
||||
return combined;
|
||||
}
|
||||
|
||||
public static byte[] decrypt (final byte[] combined, final String password) throws Exception {
|
||||
final byte[] salt = new byte[SALT_LENGTH];
|
||||
final byte[] iv = new byte[IV_LENGTH];
|
||||
final byte[] encrypted = new byte[combined.length - SALT_LENGTH - IV_LENGTH];
|
||||
|
||||
System.arraycopy(combined, 0, salt, 0, SALT_LENGTH);
|
||||
System.arraycopy(combined, SALT_LENGTH, iv, 0, IV_LENGTH);
|
||||
System.arraycopy(combined, SALT_LENGTH + IV_LENGTH, encrypted, 0, encrypted.length);
|
||||
|
||||
final SecretKey key = deriveKey(password, salt);
|
||||
final Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
final IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
|
||||
|
||||
return cipher.doFinal(encrypted);
|
||||
}
|
||||
|
||||
private static SecretKey deriveKey (final String password, final byte[] salt) throws Exception {
|
||||
final SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
|
||||
final KeySpec spec = new PBEKeySpec(password.toCharArray(), salt, ITERATIONS, KEY_LENGTH);
|
||||
final SecretKey tmp = factory.generateSecret(spec);
|
||||
return new SecretKeySpec(tmp.getEncoded(), "AES");
|
||||
}
|
||||
|
||||
private static byte[] generateRandomBytes (final int length) {
|
||||
final byte[] bytes = new byte[length];
|
||||
RANDOM.nextBytes(bytes);
|
||||
return bytes;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
|
||||
public interface Packet {
|
||||
int getId ();
|
||||
|
||||
void serialize (ByteBuf buf);
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.clientboundPackets.ClientboundCoreOutputPacket;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.serverboundPackets.ServerboundRunCommandPacket;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.serverboundPackets.ServerboundRunCoreCommandPacket;
|
||||
import me.chayapak1.chomens_bot.command.contexts.ChomeNSModCommandContext;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class PacketHandler {
|
||||
private final Bot bot;
|
||||
|
||||
public PacketHandler (final Bot bot) {
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
public void handlePacket (final PlayerEntry player, final Packet packet) {
|
||||
if (packet instanceof final ServerboundRunCoreCommandPacket t_packet) handlePacket(player, t_packet);
|
||||
else if (packet instanceof final ServerboundRunCommandPacket t_packet) handlePacket(player, t_packet);
|
||||
}
|
||||
|
||||
private void handlePacket (final PlayerEntry player, final ServerboundRunCoreCommandPacket packet) {
|
||||
final CompletableFuture<Component> future = bot.core.runTracked(packet.command);
|
||||
|
||||
if (future == null) {
|
||||
bot.chomeNSMod.send(
|
||||
player,
|
||||
new ClientboundCoreOutputPacket(
|
||||
packet.runID,
|
||||
Component.empty()
|
||||
)
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
future.thenApply(output -> {
|
||||
bot.chomeNSMod.send(
|
||||
player,
|
||||
new ClientboundCoreOutputPacket(
|
||||
packet.runID,
|
||||
output
|
||||
)
|
||||
);
|
||||
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
private void handlePacket (final PlayerEntry player, final ServerboundRunCommandPacket packet) {
|
||||
final String input = packet.input; // the input is raw, no prefix included
|
||||
|
||||
final ChomeNSModCommandContext context = new ChomeNSModCommandContext(
|
||||
bot,
|
||||
player
|
||||
);
|
||||
|
||||
bot.commandHandler.executeCommand(input, context);
|
||||
}
|
||||
}
|
54
src/main/java/me/chayapak1/chomens_bot/chomeNSMod/Types.java
Normal file
54
src/main/java/me/chayapak1/chomens_bot/chomeNSMod/Types.java
Normal file
|
@ -0,0 +1,54 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.chayapak1.chomens_bot.util.SNBTUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.UUID;
|
||||
|
||||
public class Types {
|
||||
public static UUID readUUID (final ByteBuf buf) {
|
||||
final long mostSignificantBits = buf.readLong();
|
||||
final long leastSignificantBits = buf.readLong();
|
||||
|
||||
return new UUID(mostSignificantBits, leastSignificantBits);
|
||||
}
|
||||
|
||||
public static void writeUUID (final ByteBuf buf, final UUID uuid) {
|
||||
buf.writeLong(uuid.getMostSignificantBits());
|
||||
buf.writeLong(uuid.getLeastSignificantBits());
|
||||
}
|
||||
|
||||
public static void writeString (final ByteBuf buf, final String string) {
|
||||
final byte[] bytes = string.getBytes(StandardCharsets.UTF_8);
|
||||
buf.writeInt(bytes.length);
|
||||
buf.writeBytes(bytes);
|
||||
}
|
||||
|
||||
public static String readString (final ByteBuf buf) {
|
||||
final int length = buf.readInt();
|
||||
|
||||
final byte[] bytes = new byte[length];
|
||||
buf.readBytes(bytes);
|
||||
|
||||
return new String(bytes, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
public static Component readComponent (final ByteBuf buf) {
|
||||
final String stringJSON = readString(buf);
|
||||
|
||||
try {
|
||||
return GsonComponentSerializer.gson().deserialize(stringJSON);
|
||||
} catch (final Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void writeComponent (final ByteBuf buf, final Component component) {
|
||||
final String stringJSON = SNBTUtilities.fromComponent(false, component);
|
||||
|
||||
writeString(buf, stringJSON);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod.clientboundPackets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Packet;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Types;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ClientboundCoreOutputPacket implements Packet {
|
||||
public final UUID runID;
|
||||
public final Component output;
|
||||
|
||||
public ClientboundCoreOutputPacket (final UUID runID, final Component output) {
|
||||
this.runID = runID;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
public ClientboundCoreOutputPacket (final ByteBuf buf) {
|
||||
this.runID = Types.readUUID(buf);
|
||||
this.output = Types.readComponent(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize (final ByteBuf buf) {
|
||||
Types.writeUUID(buf, this.runID);
|
||||
Types.writeComponent(buf, this.output);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod.clientboundPackets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Packet;
|
||||
|
||||
public class ClientboundHandshakePacket implements Packet {
|
||||
public ClientboundHandshakePacket () {
|
||||
}
|
||||
|
||||
public ClientboundHandshakePacket (final ByteBuf buf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize (final ByteBuf buf) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod.clientboundPackets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Packet;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Types;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class ClientboundMessagePacket implements Packet {
|
||||
public final Component message;
|
||||
|
||||
public ClientboundMessagePacket (final Component message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public ClientboundMessagePacket (final ByteBuf buf) {
|
||||
this.message = Types.readComponent(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId () {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize (final ByteBuf buf) {
|
||||
Types.writeComponent(buf, this.message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod.serverboundPackets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Packet;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Types;
|
||||
|
||||
public class ServerboundRunCommandPacket implements Packet {
|
||||
public final String input;
|
||||
|
||||
public ServerboundRunCommandPacket (final String input) {
|
||||
this.input = input;
|
||||
}
|
||||
|
||||
public ServerboundRunCommandPacket (final ByteBuf buf) {
|
||||
this.input = Types.readString(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId () {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize (final ByteBuf buf) {
|
||||
Types.writeString(buf, this.input);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod.serverboundPackets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Packet;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Types;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ServerboundRunCoreCommandPacket implements Packet {
|
||||
public final UUID runID;
|
||||
public final String command;
|
||||
|
||||
public ServerboundRunCoreCommandPacket (final UUID runID, final String command) {
|
||||
this.runID = runID;
|
||||
this.command = command;
|
||||
}
|
||||
|
||||
public ServerboundRunCoreCommandPacket (final ByteBuf buf) {
|
||||
this.runID = Types.readUUID(buf);
|
||||
this.command = Types.readString(buf);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize (final ByteBuf buf) {
|
||||
Types.writeUUID(buf, this.runID);
|
||||
Types.writeString(buf, this.command);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package me.chayapak1.chomens_bot.chomeNSMod.serverboundPackets;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.Packet;
|
||||
|
||||
public class ServerboundSuccessfulHandshakePacket implements Packet {
|
||||
public ServerboundSuccessfulHandshakePacket () {
|
||||
}
|
||||
|
||||
public ServerboundSuccessfulHandshakePacket (final ByteBuf buf) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void serialize (final ByteBuf buf) {
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
package me.chayapak1.chomens_bot.chunk;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import me.chayapak1.chomens_bot.data.chunk.ChunkPos;
|
||||
import org.geysermc.mcprotocollib.protocol.codec.MinecraftTypes;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.chunk.ChunkSection;
|
||||
|
||||
// Author: hhhzzzsss
|
||||
public class ChunkColumn {
|
||||
public final ChunkPos pos;
|
||||
public final ChunkSection[] chunks;
|
||||
|
||||
private final int minY;
|
||||
|
||||
public ChunkColumn (final ChunkPos chunkPos, final byte[] data, final int worldHeight, final int minY) {
|
||||
this.pos = chunkPos;
|
||||
this.minY = minY;
|
||||
|
||||
final int absoluteWorldHeight = Math.abs(worldHeight);
|
||||
final int absoluteMinY = Math.abs(minY);
|
||||
|
||||
final ByteBuf in = Unpooled.wrappedBuffer(data);
|
||||
final int numSections = -Math.floorDiv(-(absoluteWorldHeight + absoluteMinY), 16);
|
||||
|
||||
chunks = new ChunkSection[numSections];
|
||||
|
||||
for (int i = 0; i < numSections; i++) {
|
||||
chunks[i] = MinecraftTypes.readChunkSection(in);
|
||||
}
|
||||
}
|
||||
|
||||
public int getBlock (final int x, final int y, final int z) {
|
||||
if (chunks == null) return 0;
|
||||
|
||||
final int yIndex = (y - minY) >> 4;
|
||||
|
||||
if (yIndex >= chunks.length) return 0;
|
||||
|
||||
return chunks[yIndex].getBlock(x, y & 15, z);
|
||||
}
|
||||
|
||||
public void setBlock (final int x, final int y, final int z, final int id) {
|
||||
final int yIndex = (y - minY) >> 4;
|
||||
|
||||
if (yIndex >= chunks.length) return;
|
||||
|
||||
try {
|
||||
if (chunks[yIndex] == null) {
|
||||
chunks[yIndex] = new ChunkSection();
|
||||
chunks[yIndex].setBlock(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
chunks[yIndex].setBlock(x, y & 15, z, id);
|
||||
} catch (final Exception e) {
|
||||
// bot.logger.error(
|
||||
// Component.translatable(
|
||||
// "Failed to set block at %s %s %s in chunk %s %s with state %s!",
|
||||
//
|
||||
// Component.text(x),
|
||||
// Component.text(y),
|
||||
// Component.text(z),
|
||||
//
|
||||
// Component.text(pos.x()),
|
||||
// Component.text(pos.z()),
|
||||
//
|
||||
// Component.text(id)
|
||||
// )
|
||||
// );
|
||||
// bot.logger.error(e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,30 +1,72 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public abstract class Command {
|
||||
public final String name;
|
||||
public final String description;
|
||||
public final String[] usages;
|
||||
public String[] usages;
|
||||
public final String[] aliases;
|
||||
public final TrustLevel trustLevel;
|
||||
public final boolean consoleOnly;
|
||||
public ChatPacketType[] disallowedPacketTypes;
|
||||
|
||||
public Command (
|
||||
String name,
|
||||
String description,
|
||||
String[] usages,
|
||||
String[] aliases,
|
||||
TrustLevel trustLevel,
|
||||
boolean consoleOnly
|
||||
final String name,
|
||||
final String[] usages,
|
||||
final String[] aliases,
|
||||
final TrustLevel trustLevel
|
||||
) {
|
||||
this.name = name;
|
||||
this.usages = usages;
|
||||
this.aliases = aliases;
|
||||
this.trustLevel = trustLevel;
|
||||
this.consoleOnly = false;
|
||||
}
|
||||
|
||||
public Command (
|
||||
final String name,
|
||||
final String[] usages,
|
||||
final String[] aliases,
|
||||
final TrustLevel trustLevel,
|
||||
final boolean consoleOnly
|
||||
) {
|
||||
this.name = name;
|
||||
this.description = description;
|
||||
this.usages = usages;
|
||||
this.aliases = aliases;
|
||||
this.trustLevel = trustLevel;
|
||||
this.consoleOnly = consoleOnly;
|
||||
}
|
||||
|
||||
public Command (
|
||||
final String name,
|
||||
final String[] usages,
|
||||
final String[] aliases,
|
||||
final TrustLevel trustLevel,
|
||||
final boolean consoleOnly,
|
||||
final ChatPacketType[] disallowedPacketTypes
|
||||
) {
|
||||
this.name = name;
|
||||
this.usages = usages;
|
||||
this.aliases = aliases;
|
||||
this.trustLevel = trustLevel;
|
||||
this.consoleOnly = consoleOnly;
|
||||
this.disallowedPacketTypes = disallowedPacketTypes;
|
||||
}
|
||||
|
||||
public abstract Component execute (CommandContext context) throws Exception;
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return "Command{" +
|
||||
"name='" + name + '\'' +
|
||||
", usages=" + Arrays.toString(usages) +
|
||||
", aliases=" + Arrays.toString(aliases) +
|
||||
", trustLevel=" + trustLevel +
|
||||
", consoleOnly=" + consoleOnly +
|
||||
", disallowedPacketTypes=" + Arrays.toString(disallowedPacketTypes) +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,25 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class CommandContext {
|
||||
public static final Component UNKNOWN_ARGUMENT_COMPONENT = Component.text("???").style(Style.style(TextDecoration.UNDERLINED));
|
||||
public static final Component UNKNOWN_ARGUMENT_COMPONENT = Component
|
||||
.text("???")
|
||||
.style(Style.style(TextDecoration.UNDERLINED));
|
||||
private static final Pattern FLAGS_PATTERN = Pattern
|
||||
.compile("^\\s*(?:--|-)([^\\s0-9]\\S*)"); // modified from HBot
|
||||
|
||||
public final Bot bot;
|
||||
|
||||
|
@ -19,13 +29,15 @@ public class CommandContext {
|
|||
|
||||
public final boolean inGame;
|
||||
|
||||
public TrustLevel trustLevel = TrustLevel.PUBLIC;
|
||||
|
||||
public String commandName = null;
|
||||
public String userInputCommandName = null;
|
||||
|
||||
public String[] fullArgs;
|
||||
public String[] args;
|
||||
|
||||
public CommandContext(Bot bot, String prefix, PlayerEntry sender, boolean inGame) {
|
||||
public CommandContext (final Bot bot, final String prefix, final PlayerEntry sender, final boolean inGame) {
|
||||
this.bot = bot;
|
||||
this.prefix = prefix;
|
||||
this.sender = sender;
|
||||
|
@ -33,20 +45,24 @@ public class CommandContext {
|
|||
}
|
||||
|
||||
public Component displayName () { return Component.empty(); }
|
||||
public void sendOutput (Component component) {}
|
||||
|
||||
public void sendOutput (final Component component) { }
|
||||
|
||||
// args parsing stuff
|
||||
private int argsPosition = 0;
|
||||
|
||||
public String getString (boolean greedy, boolean required) throws CommandException { return getString(greedy, required, "string"); }
|
||||
public String getString (boolean greedy, boolean required, boolean returnLowerCase) throws CommandException { return getString(greedy, returnLowerCase, required, "string"); }
|
||||
private String getString (boolean greedy, boolean required, String type) throws CommandException { return getString(greedy, false, required, type); }
|
||||
private String getString (boolean greedy, boolean returnLowerCase, boolean required, String type) throws CommandException {
|
||||
public String getString (final boolean greedy, final boolean required) throws CommandException { return getString(greedy, required, "string"); }
|
||||
|
||||
public String getString (final boolean greedy, final boolean required, final boolean returnLowerCase) throws CommandException { return getString(greedy, returnLowerCase, required, "string"); }
|
||||
|
||||
private String getString (final boolean greedy, final boolean required, final String type) throws CommandException { return getString(greedy, false, required, type); }
|
||||
|
||||
private String getString (final boolean greedy, final boolean returnLowerCase, final boolean required, final String type) throws CommandException {
|
||||
if (argsPosition >= args.length || args[argsPosition] == null) {
|
||||
if (required) {
|
||||
throw new CommandException(
|
||||
Component.translatable(
|
||||
"Expected %s at position %s (%s %s)",
|
||||
"arguments_parsing.error.expected_string",
|
||||
Component.text(type),
|
||||
Component.text(argsPosition),
|
||||
Component.text(prefix + userInputCommandName),
|
||||
|
@ -55,7 +71,19 @@ public class CommandContext {
|
|||
Component
|
||||
.text(String.join(" ", args))
|
||||
.append(Component.space())
|
||||
.append(UNKNOWN_ARGUMENT_COMPONENT)
|
||||
.append(UNKNOWN_ARGUMENT_COMPONENT),
|
||||
inGame ?
|
||||
Component
|
||||
.space()
|
||||
.append(
|
||||
Component.translatable("[%s]")
|
||||
.arguments(
|
||||
Component
|
||||
.translatable("arguments_parsing.hover.usages")
|
||||
.clickEvent(ClickEvent.suggestCommand(prefix + "help " + this.commandName))
|
||||
)
|
||||
) :
|
||||
Component.empty()
|
||||
)
|
||||
);
|
||||
} else {
|
||||
|
@ -63,52 +91,183 @@ public class CommandContext {
|
|||
}
|
||||
}
|
||||
|
||||
final String string = greedy ?
|
||||
String.join(" ", Arrays.copyOfRange(args, argsPosition, args.length)) :
|
||||
args[argsPosition];
|
||||
final String greedyString = String.join(" ", Arrays.copyOfRange(args, argsPosition, args.length));
|
||||
|
||||
final StringBuilder string = new StringBuilder();
|
||||
|
||||
if (greedy) {
|
||||
string.append(greedyString);
|
||||
} else if (
|
||||
greedyString.length() > 1 &&
|
||||
(greedyString.startsWith("'") || greedyString.startsWith("\""))
|
||||
) {
|
||||
// parses arguments with quotes
|
||||
|
||||
final char quote = greedyString.charAt(0);
|
||||
|
||||
int pointer = 1; // skips quote
|
||||
|
||||
while (true) {
|
||||
if (pointer >= greedyString.length()) {
|
||||
if (greedyString.charAt(pointer - 1) != quote) {
|
||||
throw new CommandException(
|
||||
Component
|
||||
.translatable("arguments_parsing.error.unterminated_quote")
|
||||
.arguments(
|
||||
Component.text(greedyString, bot.colorPalette.string),
|
||||
Component.text(quote, NamedTextColor.YELLOW)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
final char character = greedyString.charAt(pointer);
|
||||
|
||||
pointer++;
|
||||
|
||||
if (character == ' ') {
|
||||
argsPosition++;
|
||||
}
|
||||
|
||||
if (character == '\\') {
|
||||
if (pointer >= greedyString.length()) {
|
||||
throw new CommandException(
|
||||
Component
|
||||
.translatable("arguments_parsing.error.unterminated_escape")
|
||||
.arguments(
|
||||
Component
|
||||
.text(greedyString)
|
||||
.color(bot.colorPalette.string)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final char nextCharacter = greedyString.charAt(pointer); // pointer is already incremented above
|
||||
|
||||
final char toAdd = switch (nextCharacter) {
|
||||
case 'n' -> '\n';
|
||||
case 't' -> '\t';
|
||||
case 'r' -> '\r';
|
||||
default -> nextCharacter;
|
||||
};
|
||||
|
||||
string.append(toAdd);
|
||||
|
||||
pointer++;
|
||||
} else if (character == quote) {
|
||||
break;
|
||||
} else {
|
||||
string.append(character);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// else just get the current argument
|
||||
string.append(args[argsPosition]);
|
||||
}
|
||||
|
||||
argsPosition++;
|
||||
|
||||
return returnLowerCase ? string.toLowerCase() : string;
|
||||
final String result = string.toString();
|
||||
|
||||
return returnLowerCase ? result.toLowerCase() : result;
|
||||
}
|
||||
|
||||
public Integer getInteger (boolean required) throws CommandException {
|
||||
public String getAction () throws CommandException {
|
||||
return getString(false, true, true, "action");
|
||||
}
|
||||
|
||||
public List<String> getFlags (final String... allowedFlags) throws CommandException { return getFlags(false, allowedFlags); }
|
||||
|
||||
public List<String> getFlags (final boolean returnLowerCase, final String... allowedFlags) throws CommandException {
|
||||
final List<String> flags = new ArrayList<>();
|
||||
|
||||
String flag = getFlag(returnLowerCase, allowedFlags);
|
||||
|
||||
while (flag != null) {
|
||||
flags.add(flag);
|
||||
flag = getFlag(returnLowerCase, allowedFlags);
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
||||
private String getFlag (final boolean returnLowerCase, final String[] allowedFlagsArray) throws CommandException {
|
||||
final List<String> allowedFlags = Arrays.asList(allowedFlagsArray);
|
||||
|
||||
final String string = getString(false, false, returnLowerCase);
|
||||
|
||||
if (string.isBlank()) return null;
|
||||
|
||||
final Matcher matcher = FLAGS_PATTERN.matcher(string);
|
||||
|
||||
if (matcher.find()) {
|
||||
final String match = matcher.group(1);
|
||||
|
||||
if (allowedFlags.contains(match)) return match;
|
||||
}
|
||||
|
||||
argsPosition--; // getString incremented argsPosition
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Integer getInteger (final boolean required) throws CommandException {
|
||||
final String string = getString(false, required, "integer");
|
||||
|
||||
if (string.isEmpty()) return null;
|
||||
|
||||
try {
|
||||
return Integer.parseInt(string);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new CommandException(Component.text("Invalid integer"));
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("integer")));
|
||||
}
|
||||
}
|
||||
|
||||
public Double getDouble (boolean required) throws CommandException {
|
||||
public Long getLong (final boolean required) throws CommandException {
|
||||
final String string = getString(false, required, "long");
|
||||
|
||||
if (string.isEmpty()) return null;
|
||||
|
||||
try {
|
||||
return Long.parseLong(string);
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("long")));
|
||||
}
|
||||
}
|
||||
|
||||
public Double getDouble (final boolean required, final boolean allowInfinite) throws CommandException {
|
||||
final String string = getString(false, required, "double");
|
||||
|
||||
if (string.isEmpty()) return null;
|
||||
|
||||
try {
|
||||
return Double.parseDouble(string);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new CommandException(Component.text("Invalid double"));
|
||||
final double parsedDouble = Double.parseDouble(string);
|
||||
|
||||
if (!Double.isFinite(parsedDouble) && !allowInfinite) throw new NumberFormatException();
|
||||
else return parsedDouble;
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("double")));
|
||||
}
|
||||
}
|
||||
|
||||
public Float getFloat (boolean required) throws CommandException {
|
||||
public Float getFloat (final boolean required, final boolean allowInfinite) throws CommandException {
|
||||
final String string = getString(false, required, "float");
|
||||
|
||||
if (string.isEmpty()) return null;
|
||||
|
||||
try {
|
||||
return Float.parseFloat(string);
|
||||
} catch (NumberFormatException e) {
|
||||
throw new CommandException(Component.text("Invalid float"));
|
||||
final float parsedFloat = Float.parseFloat(string);
|
||||
|
||||
if (!Float.isFinite(parsedFloat) && !allowInfinite) throw new NumberFormatException();
|
||||
else return parsedFloat;
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("float")));
|
||||
}
|
||||
}
|
||||
|
||||
public Boolean getBoolean (boolean required) throws CommandException {
|
||||
public Boolean getBoolean (final boolean required) throws CommandException {
|
||||
final String string = getString(false, required, "boolean");
|
||||
|
||||
if (string.isEmpty()) return null;
|
||||
|
@ -116,24 +275,42 @@ public class CommandContext {
|
|||
return switch (string) {
|
||||
case "true" -> true;
|
||||
case "false" -> false;
|
||||
default -> throw new CommandException(Component.text("Invalid boolean"));
|
||||
default -> throw new CommandException(Component.translatable("arguments_parsing.error.invalid_type", Component.text("boolean")));
|
||||
};
|
||||
}
|
||||
|
||||
public <T extends Enum<T>> T getEnum (Class<T> enumClass) throws CommandException {
|
||||
final String string = getString(false, true, enumClass.getSimpleName());
|
||||
public <T extends Enum<T>> T getEnum (final boolean required, final Class<T> enumClass) throws CommandException {
|
||||
final String string = getString(false, required, enumClass.getSimpleName());
|
||||
|
||||
if (string.isEmpty()) return null;
|
||||
|
||||
try {
|
||||
return Enum.valueOf(enumClass, string.toUpperCase());
|
||||
} catch (IllegalArgumentException | NullPointerException e) {
|
||||
throw new CommandException(Component.text("Invalid enum"));
|
||||
} catch (final IllegalArgumentException | NullPointerException e) {
|
||||
final T[] values = enumClass.getEnumConstants();
|
||||
|
||||
throw new CommandException(
|
||||
Component.translatable(
|
||||
"arguments_parsing.error.invalid_enum",
|
||||
Component.text(enumClass.getSimpleName()),
|
||||
Component.text(Arrays.toString(values))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkOverloadArgs (int maximumArgs) throws CommandException {
|
||||
if (args.length > maximumArgs) throw new CommandException(
|
||||
public void checkOverloadArgs (final int maximumArgs) throws CommandException {
|
||||
final String joined = String.join(" ", args);
|
||||
|
||||
final String quotesReplaced = joined.replaceAll("([\"'])(?:\\.|(?!\1).)*\1", "i");
|
||||
|
||||
final int count = quotesReplaced.isBlank() ?
|
||||
0 :
|
||||
quotesReplaced.split("\\s+").length;
|
||||
|
||||
if (count > maximumArgs) throw new CommandException(
|
||||
Component.translatable(
|
||||
"Too many arguments, expected %s max",
|
||||
"arguments_parsing.error.too_many_arguments",
|
||||
Component.text(maximumArgs)
|
||||
)
|
||||
);
|
||||
|
|
|
@ -5,7 +5,7 @@ import net.kyori.adventure.text.Component;
|
|||
public class CommandException extends Exception {
|
||||
public final Component message;
|
||||
|
||||
public CommandException (Component message) {
|
||||
public CommandException (final Component message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
|
||||
public final class CommonFlags {
|
||||
public static final String IGNORE_CASE = "ignorecase";
|
||||
public static final String REGEX = "regex";
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
public class ConsoleCommandContext extends CommandContext {
|
||||
private final Bot bot;
|
||||
|
||||
public ConsoleCommandContext (Bot bot, String prefix) {
|
||||
super(bot, prefix, bot.players.getBotEntry() /* real */, false);
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (Component component) {
|
||||
final String message = ComponentUtilities.stringifyAnsi(component);
|
||||
bot.logger.info(message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component displayName () {
|
||||
return sender.displayName.color(NamedTextColor.YELLOW);
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.CodeBlockUtilities;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.events.message.MessageReceivedEvent;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DiscordCommandContext extends CommandContext {
|
||||
private final MessageReceivedEvent event;
|
||||
|
||||
private final Bot bot;
|
||||
|
||||
public DiscordCommandContext(Bot bot, String prefix, MessageReceivedEvent event) {
|
||||
super(
|
||||
bot,
|
||||
prefix,
|
||||
new PlayerEntry(
|
||||
new GameProfile(
|
||||
UUID.nameUUIDFromBytes(("OfflinePlayer:" + event.getAuthor().getName()).getBytes()),
|
||||
event.getAuthor().getName()
|
||||
),
|
||||
GameMode.SURVIVAL,
|
||||
-69420,
|
||||
Component.text(event.getAuthor().getName()),
|
||||
0L,
|
||||
null,
|
||||
new byte[0],
|
||||
true
|
||||
),
|
||||
false
|
||||
);
|
||||
this.bot = bot;
|
||||
this.event = event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (Component component) {
|
||||
final String output = ComponentUtilities.stringifyAnsi(component);
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle("Output");
|
||||
builder.setColor(Color.decode(bot.config.discord.embedColors.normal));
|
||||
builder.setDescription("```ansi\n" + CodeBlockUtilities.escape(output.replace("\u001b[9", "\u001b[3")) + "\n```");
|
||||
|
||||
final MessageEmbed embed = builder.build();
|
||||
|
||||
event.getMessage().replyEmbeds(embed).queue();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component displayName () {
|
||||
return Component.text(event.getAuthor().getName());
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class PlayerCommandContext extends CommandContext {
|
||||
public final String playerName;
|
||||
|
||||
public final String selector;
|
||||
|
||||
private final Bot bot;
|
||||
|
||||
public PlayerCommandContext (Bot bot, String playerName, String prefix, String selector, PlayerEntry sender) {
|
||||
super(bot, prefix, sender, true);
|
||||
this.bot = bot;
|
||||
this.playerName = playerName;
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (Component message) {
|
||||
bot.chat.tellraw(
|
||||
Component.translatable(
|
||||
"%s",
|
||||
message,
|
||||
Component.text("chomens_bot_command_output" + ((commandName != null) ? "_" + commandName : ""))
|
||||
),
|
||||
selector
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component displayName () {
|
||||
return sender.displayName;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,47 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
|
||||
import me.chayapak1.chomens_bot.Configuration;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import net.dv8tion.jda.api.entities.Role;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public enum TrustLevel {
|
||||
PUBLIC,
|
||||
TRUSTED,
|
||||
OWNER
|
||||
PUBLIC(0, Component.text(I18nUtilities.get("trust_level.public"), NamedTextColor.GREEN)),
|
||||
TRUSTED(1, Component.text(I18nUtilities.get("trust_level.trusted"), NamedTextColor.RED)),
|
||||
ADMIN(2, Component.text(I18nUtilities.get("trust_level.admin"), NamedTextColor.DARK_RED)),
|
||||
OWNER(3, Component.text(I18nUtilities.get("trust_level.owner"), NamedTextColor.LIGHT_PURPLE));
|
||||
|
||||
public static final TrustLevel MAX = values()[values().length - 1];
|
||||
|
||||
public final int level;
|
||||
public final Component component;
|
||||
|
||||
TrustLevel (final int level, final Component component) {
|
||||
this.level = level;
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
public static TrustLevel fromDiscordRoles (final List<Role> roles) {
|
||||
if (Main.discord == null || Main.discord.options == null) return PUBLIC;
|
||||
|
||||
final Configuration.Discord options = Main.discord.options;
|
||||
|
||||
final Map<String, TrustLevel> roleToLevel = Map.of(
|
||||
options.ownerRoleName.toLowerCase(), OWNER,
|
||||
options.adminRoleName.toLowerCase(), ADMIN,
|
||||
options.trustedRoleName.toLowerCase(), TRUSTED
|
||||
);
|
||||
|
||||
for (final Role role : roles) {
|
||||
final TrustLevel level = roleToLevel.get(role.getName().toLowerCase());
|
||||
if (level != null) return level;
|
||||
}
|
||||
|
||||
return PUBLIC;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package me.chayapak1.chomens_bot.command.contexts;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.chomeNSMod.clientboundPackets.ClientboundMessagePacket;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class ChomeNSModCommandContext extends CommandContext {
|
||||
public ChomeNSModCommandContext (final Bot bot, final PlayerEntry sender) {
|
||||
super(
|
||||
bot,
|
||||
".cbot ", // intentionally hardcoded
|
||||
sender,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (final Component component) {
|
||||
final Component rendered = I18nUtilities.render(component);
|
||||
bot.chomeNSMod.send(
|
||||
sender,
|
||||
new ClientboundMessagePacket(rendered)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component displayName () {
|
||||
return sender.displayName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package me.chayapak1.chomens_bot.command.contexts;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.data.logging.LogType;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
|
||||
public class ConsoleCommandContext extends CommandContext {
|
||||
private final Bot bot;
|
||||
|
||||
public ConsoleCommandContext (final Bot bot, final String prefix) {
|
||||
super(
|
||||
bot,
|
||||
prefix,
|
||||
bot.players.getBotEntry() != null ?
|
||||
bot.players.getBotEntry() :
|
||||
new PlayerEntry(
|
||||
new GameProfile(
|
||||
UUIDUtilities.getOfflineUUID(bot.username),
|
||||
bot.username
|
||||
),
|
||||
GameMode.CREATIVE,
|
||||
-69420,
|
||||
Component.text(bot.username),
|
||||
0,
|
||||
null,
|
||||
new byte[0],
|
||||
true
|
||||
),
|
||||
false
|
||||
);
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (final Component component) {
|
||||
final Component rendered = I18nUtilities.render(component);
|
||||
bot.logger.log(LogType.COMMAND_OUTPUT, rendered, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component displayName () {
|
||||
return sender.displayName.color(NamedTextColor.YELLOW);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
package me.chayapak1.chomens_bot.command.contexts;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.CodeBlockUtilities;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import net.dv8tion.jda.api.EmbedBuilder;
|
||||
import net.dv8tion.jda.api.entities.Member;
|
||||
import net.dv8tion.jda.api.entities.MessageEmbed;
|
||||
import net.dv8tion.jda.api.utils.FileUpload;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
|
||||
import java.awt.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public class DiscordCommandContext extends CommandContext {
|
||||
public final Member member;
|
||||
public final String name;
|
||||
public final Consumer<FileUpload> replyFiles;
|
||||
public final Consumer<MessageEmbed> replyEmbed;
|
||||
|
||||
private final Bot bot;
|
||||
|
||||
public DiscordCommandContext (
|
||||
final Bot bot,
|
||||
final String prefix,
|
||||
final Member member,
|
||||
final String name,
|
||||
final Consumer<FileUpload> replyFiles,
|
||||
final Consumer<MessageEmbed> replyEmbed
|
||||
) {
|
||||
super(
|
||||
bot,
|
||||
prefix,
|
||||
new PlayerEntry(
|
||||
new GameProfile(
|
||||
UUIDUtilities.getOfflineUUID(name),
|
||||
name
|
||||
),
|
||||
GameMode.SURVIVAL,
|
||||
-69420,
|
||||
Component.text(name),
|
||||
0L,
|
||||
null,
|
||||
new byte[0],
|
||||
true
|
||||
),
|
||||
false
|
||||
);
|
||||
this.bot = bot;
|
||||
this.member = member;
|
||||
this.name = name;
|
||||
this.replyFiles = replyFiles;
|
||||
this.replyEmbed = replyEmbed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (final Component component) {
|
||||
final Component rendered = I18nUtilities.render(component);
|
||||
|
||||
String output = ComponentUtilities.stringifyDiscordAnsi(rendered);
|
||||
|
||||
if (output.length() > 2048) {
|
||||
output = ComponentUtilities.stringify(rendered);
|
||||
|
||||
replyFiles.accept(
|
||||
FileUpload.fromData(
|
||||
output.getBytes(StandardCharsets.UTF_8),
|
||||
String.format("output-%d.txt", System.currentTimeMillis())
|
||||
)
|
||||
);
|
||||
} else {
|
||||
final EmbedBuilder builder = new EmbedBuilder();
|
||||
builder.setTitle("Output");
|
||||
builder.setColor(Color.decode(bot.config.discord.embedColors.normal));
|
||||
builder.setDescription("```ansi\n" + CodeBlockUtilities.escape(output) + "\n```");
|
||||
|
||||
final MessageEmbed embed = builder.build();
|
||||
|
||||
replyEmbed.accept(embed);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component displayName () {
|
||||
return Component.text(name);
|
||||
}
|
||||
}
|
|
@ -1,25 +1,27 @@
|
|||
package me.chayapak1.chomens_bot.command;
|
||||
package me.chayapak1.chomens_bot.command.contexts;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class IRCCommandContext extends CommandContext {
|
||||
private final Bot bot;
|
||||
private final String nickName;
|
||||
|
||||
public IRCCommandContext (Bot bot, String prefix, String nickName) {
|
||||
public IRCCommandContext (final Bot bot, final String prefix, final String nickName) {
|
||||
super(
|
||||
bot,
|
||||
prefix,
|
||||
new PlayerEntry(
|
||||
new GameProfile(
|
||||
UUID.nameUUIDFromBytes(("OfflinePlayer:" + nickName).getBytes()),
|
||||
UUIDUtilities.getOfflineUUID(nickName),
|
||||
nickName
|
||||
),
|
||||
GameMode.SURVIVAL,
|
||||
|
@ -37,8 +39,9 @@ public class IRCCommandContext extends CommandContext {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (Component component) {
|
||||
bot.irc.sendMessage(bot, ComponentUtilities.stringify(component));
|
||||
public void sendOutput (final Component component) {
|
||||
final Component rendered = I18nUtilities.render(component);
|
||||
Main.irc.sendMessage(bot, ComponentUtilities.stringifyAnsi(rendered));
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,61 @@
|
|||
package me.chayapak1.chomens_bot.command.contexts;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class PlayerCommandContext extends CommandContext {
|
||||
public final String playerName;
|
||||
|
||||
public final String selector;
|
||||
|
||||
public final ChatPacketType packetType;
|
||||
|
||||
private final Bot bot;
|
||||
|
||||
public PlayerCommandContext (
|
||||
final Bot bot,
|
||||
final String playerName,
|
||||
final String prefix,
|
||||
final String selector,
|
||||
final PlayerEntry sender,
|
||||
final ChatPacketType packetType
|
||||
) {
|
||||
super(bot, prefix, sender, true);
|
||||
this.bot = bot;
|
||||
this.playerName = playerName;
|
||||
this.selector = selector;
|
||||
this.packetType = packetType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (final Component component) {
|
||||
sendOutput(component, false);
|
||||
}
|
||||
|
||||
public void sendOutput (final Component component, final boolean onlyToSender) {
|
||||
final Component rendered = I18nUtilities.render(component);
|
||||
|
||||
final String selector = onlyToSender
|
||||
? UUIDUtilities.selector(this.sender.profile.getId())
|
||||
: this.selector;
|
||||
|
||||
bot.chat.tellraw(
|
||||
Component.translatable(
|
||||
"%s",
|
||||
rendered,
|
||||
Component.text("chomens_bot_command_output" + ((commandName != null) ? "_" + commandName : ""))
|
||||
),
|
||||
selector
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component displayName () {
|
||||
return sender.displayName;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package me.chayapak1.chomens_bot.command.contexts;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
public class RemoteCommandContext extends CommandContext {
|
||||
public final Bot targetBot;
|
||||
public final CommandContext source;
|
||||
|
||||
public RemoteCommandContext (final Bot targetBot, final CommandContext source) {
|
||||
super(targetBot, source.prefix, source.sender, false);
|
||||
|
||||
this.targetBot = targetBot;
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendOutput (final Component component) {
|
||||
// we do not need rendering here, since that is handled by the source
|
||||
source.sendOutput(
|
||||
Component
|
||||
.translatable(
|
||||
"[%s] %s",
|
||||
Component.text(targetBot.getServerString(), NamedTextColor.GRAY),
|
||||
Component.empty()
|
||||
.color(NamedTextColor.WHITE)
|
||||
.append(component)
|
||||
)
|
||||
.color(NamedTextColor.DARK_GRAY)
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class AuthCommand extends Command {
|
||||
public AuthCommand () {
|
||||
super(
|
||||
"auth",
|
||||
new String[] { "[TrustLevel]" },
|
||||
new String[] {},
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final boolean allowSettingOthers = context.trustLevel == TrustLevel.MAX;
|
||||
|
||||
if (!allowSettingOthers) context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
TrustLevel trustLevel = context.getEnum(false, TrustLevel.class);
|
||||
if (trustLevel == null) trustLevel = context.trustLevel;
|
||||
|
||||
if (trustLevel.level > context.trustLevel.level) throw new CommandException(
|
||||
Component.translatable("commands.auth.error.privilege_escalate")
|
||||
);
|
||||
|
||||
final String targetString = context.getString(true, false);
|
||||
|
||||
PlayerEntry target = null;
|
||||
if (allowSettingOthers && !targetString.isEmpty()) target = bot.players.getEntry(targetString);
|
||||
if (target == null) target = context.sender;
|
||||
|
||||
target.persistingData.authenticatedTrustLevel = trustLevel;
|
||||
|
||||
if (target.equals(context.sender)) {
|
||||
return Component.translatable(
|
||||
"commands.auth.self",
|
||||
bot.colorPalette.defaultColor,
|
||||
target.persistingData.authenticatedTrustLevel.component
|
||||
);
|
||||
} else {
|
||||
return Component.translatable(
|
||||
"commands.auth.others",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(target.profile.getName(), bot.colorPalette.username),
|
||||
target.persistingData.authenticatedTrustLevel.component
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.selfCares.essentials.VanishSelfCare;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
|
@ -13,55 +13,58 @@ public class BotVisibilityCommand extends Command {
|
|||
public BotVisibilityCommand () {
|
||||
super(
|
||||
"botvisibility",
|
||||
"Changes the bot's visibility",
|
||||
new String[] { "<true|false>", "<on|off>", "" },
|
||||
new String[] { "botvis", "togglevis", "togglevisibility" },
|
||||
TrustLevel.TRUSTED,
|
||||
false
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String action = context.getString(false, false, false);
|
||||
|
||||
if (action.isEmpty()) {
|
||||
final boolean visibility = bot.selfCare.visibility;
|
||||
bot.selfCare.visibility = !visibility;
|
||||
final VanishSelfCare vanish = bot.selfCare.find(VanishSelfCare.class);
|
||||
|
||||
final NamedTextColor greenOrGold = bot.selfCare.visibility ? NamedTextColor.GREEN : NamedTextColor.GOLD;
|
||||
final String visibleOrInvisible = bot.selfCare.visibility ? "visible" : "invisible";
|
||||
final String disableOrEnable = bot.selfCare.visibility ? "disable" : "enable";
|
||||
bot.core.run("/essentials:vanish " + bot.profile.getName() + " " + disableOrEnable);
|
||||
return Component.empty()
|
||||
.append(Component.text("The bot's visibility is now "))
|
||||
.append(Component.text(visibleOrInvisible).color(greenOrGold))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
if (action.isEmpty()) {
|
||||
vanish.visible = !vanish.visible;
|
||||
vanish.needsRunning = true;
|
||||
|
||||
final NamedTextColor greenOrGold = vanish.visible ? NamedTextColor.GREEN : NamedTextColor.GOLD;
|
||||
|
||||
final String visibleOrInvisible = vanish.visible ? "visible" : "invisible";
|
||||
|
||||
return Component.translatable(
|
||||
"commands.botvisibility.message",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable("commands.botvisibility." + visibleOrInvisible, greenOrGold)
|
||||
);
|
||||
} else {
|
||||
switch (action) {
|
||||
case "on", "true" -> {
|
||||
bot.selfCare.visibility = true;
|
||||
bot.core.run("/essentials:vanish " + bot.profile.getName() + " disable");
|
||||
return Component.empty()
|
||||
.append(Component.text("The bot's visibility is now "))
|
||||
.append(Component.text("visible").color(NamedTextColor.GREEN))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
vanish.visible = true;
|
||||
vanish.needsRunning = true;
|
||||
|
||||
return Component.translatable(
|
||||
"commands.botvisibility.message",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable("commands.botvisibility.visible", NamedTextColor.GREEN)
|
||||
);
|
||||
}
|
||||
case "off", "false" -> {
|
||||
bot.selfCare.visibility = false;
|
||||
bot.core.run("/essentials:vanish " + bot.profile.getName() + " enable");
|
||||
return Component.empty()
|
||||
.append(Component.text("The bot's visibility is now "))
|
||||
.append(Component.text("invisible").color(NamedTextColor.GOLD))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
}
|
||||
default -> {
|
||||
throw new CommandException(Component.text("Invalid action"));
|
||||
vanish.visible = false;
|
||||
vanish.needsRunning = true;
|
||||
|
||||
return Component.translatable(
|
||||
"commands.botvisibility.message",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable("commands.botvisibility.invisible", NamedTextColor.GOLD)
|
||||
);
|
||||
}
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,16 +11,14 @@ public class BruhifyCommand extends Command {
|
|||
public BruhifyCommand () {
|
||||
super(
|
||||
"bruhify",
|
||||
"RecycleBots bruhify but actionbar",
|
||||
new String[] { "[message]" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
bot.bruhify.bruhifyText = context.getString(true, false);
|
||||
|
|
|
@ -5,7 +5,9 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
|
@ -15,16 +17,16 @@ public class ClearChatCommand extends Command {
|
|||
public ClearChatCommand () {
|
||||
super(
|
||||
"clearchat",
|
||||
"Clears the chat",
|
||||
new String[] { "[player]" },
|
||||
new String[] { "cc" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[] { ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String name = context.getString(true, false);
|
||||
|
@ -32,26 +34,32 @@ public class ClearChatCommand extends Command {
|
|||
if (!name.isEmpty()) {
|
||||
final PlayerEntry entry = bot.players.getEntry(name);
|
||||
|
||||
if (entry == null) throw new CommandException(Component.text("Invalid player name"));
|
||||
if (entry == null)
|
||||
throw new CommandException(Component.translatable("commands.generic.error.invalid_player"));
|
||||
|
||||
final UUID uuid = entry.profile.getId();
|
||||
|
||||
bot.chat.tellraw(
|
||||
Component.empty()
|
||||
.append(Component.text("\n".repeat(1000)))
|
||||
.append(
|
||||
Component.empty()
|
||||
.append(Component.text("Your chat has been cleared by "))
|
||||
.append(context.displayName())
|
||||
.color(NamedTextColor.DARK_GREEN)
|
||||
),
|
||||
I18nUtilities.render(
|
||||
Component.empty()
|
||||
.append(Component.text("\n".repeat(1000)))
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.clearchat.specific",
|
||||
NamedTextColor.DARK_GREEN,
|
||||
context.displayName()
|
||||
)
|
||||
)
|
||||
),
|
||||
uuid
|
||||
);
|
||||
} else {
|
||||
bot.chat.tellraw(
|
||||
Component.empty()
|
||||
.append(Component.text("\n".repeat(1000)))
|
||||
.append(Component.text("The chat has been cleared").color(NamedTextColor.DARK_GREEN))
|
||||
I18nUtilities.render(
|
||||
Component.empty()
|
||||
.append(Component.text("\n".repeat(1000)))
|
||||
.append(Component.translatable("commands.clearchat.everyone", NamedTextColor.DARK_GREEN))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -11,22 +11,23 @@ public class ClearChatQueueCommand extends Command {
|
|||
public ClearChatQueueCommand () {
|
||||
super(
|
||||
"clearchatqueue",
|
||||
"Clears the bots chat queue",
|
||||
new String[] {},
|
||||
new String[] { "ccq" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(0);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
bot.chat.clearQueue();
|
||||
|
||||
return null;
|
||||
return Component.translatable(
|
||||
"commands.clearchatqueue.output",
|
||||
bot.colorPalette.defaultColor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,12 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.CommandLoop;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.data.cloop.CommandLoop;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -18,34 +18,43 @@ public class CloopCommand extends Command {
|
|||
public CloopCommand () {
|
||||
super(
|
||||
"cloop",
|
||||
"Loop commands",
|
||||
new String[] { "add <interval> <command>", "remove <index>", "clear", "list" },
|
||||
new String[] { "add <interval> <ChronoUnit> <command>", "remove <index>", "clear", "list" },
|
||||
new String[] { "commandloop" },
|
||||
TrustLevel.TRUSTED,
|
||||
false
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String action = context.getString(false, true, true);
|
||||
final String action = context.getAction();
|
||||
|
||||
switch (action) {
|
||||
case "add" -> {
|
||||
int interval = context.getInteger(true);
|
||||
long interval = context.getLong(true);
|
||||
if (interval < 1) interval = 1;
|
||||
|
||||
final ChronoUnit unit = context.getEnum(true, ChronoUnit.class);
|
||||
|
||||
if (unit == ChronoUnit.NANOS && interval < 1000)
|
||||
throw new CommandException(Component.translatable("commands.cloop.add.error.too_low_nanoseconds"));
|
||||
|
||||
final String command = context.getString(true, true);
|
||||
|
||||
bot.cloop.add(interval, command);
|
||||
try {
|
||||
bot.cloop.add(unit, interval, command);
|
||||
} catch (final Exception e) {
|
||||
throw new CommandException(Component.text(e.toString()));
|
||||
}
|
||||
|
||||
return Component.translatable(
|
||||
"Added %s with interval %s to the cloops",
|
||||
Component.text(command).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
Component.text(interval).color(ColorUtilities.getColorByString(bot.config.colorPalette.number))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
"commands.cloop.add.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(command, bot.colorPalette.string),
|
||||
Component.text(interval, bot.colorPalette.number),
|
||||
Component.text(unit.toString(), bot.colorPalette.string)
|
||||
);
|
||||
}
|
||||
case "remove" -> {
|
||||
context.checkOverloadArgs(2);
|
||||
|
@ -56,18 +65,19 @@ public class CloopCommand extends Command {
|
|||
final CommandLoop cloop = bot.cloop.remove(index);
|
||||
|
||||
return Component.translatable(
|
||||
"Removed cloop %s",
|
||||
Component.text(cloop.command()).color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
} catch (IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) {
|
||||
throw new CommandException(Component.text("Invalid index"));
|
||||
"commands.cloop.remove.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(cloop.command(), bot.colorPalette.string)
|
||||
);
|
||||
} catch (final IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) {
|
||||
throw new CommandException(Component.translatable("commands.generic.error.invalid_index"));
|
||||
}
|
||||
}
|
||||
case "clear" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
bot.cloop.clear();
|
||||
return Component.text("Cleared all cloops").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.cloop.clear.output", bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "list" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
@ -75,29 +85,31 @@ public class CloopCommand extends Command {
|
|||
final List<Component> cloopsComponent = new ArrayList<>();
|
||||
|
||||
int index = 0;
|
||||
for (CommandLoop command : bot.cloop.loops) {
|
||||
for (final CommandLoop command : bot.cloop.loops) {
|
||||
cloopsComponent.add(
|
||||
Component.translatable(
|
||||
"%s › %s (%s)",
|
||||
Component.text(index).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
|
||||
Component.text(command.command()).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
Component.text(command.interval()).color(ColorUtilities.getColorByString(bot.config.colorPalette.number))
|
||||
).color(NamedTextColor.DARK_GRAY)
|
||||
"%s › %s (%s %s)",
|
||||
NamedTextColor.DARK_GRAY,
|
||||
Component.text(index, bot.colorPalette.number),
|
||||
Component.text(command.command(), bot.colorPalette.string),
|
||||
Component.text(command.interval(), bot.colorPalette.number),
|
||||
Component.text(command.unit().toString(), bot.colorPalette.string)
|
||||
)
|
||||
);
|
||||
index++;
|
||||
}
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Cloops ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(bot.cloop.loops.size()).color(NamedTextColor.GRAY))
|
||||
.append(Component.text(")").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.translatable("commands.cloop.list.cloops_text", NamedTextColor.GREEN))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(bot.cloop.loops.size(), NamedTextColor.GRAY))
|
||||
.append(Component.text(")", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.join(JoinConfiguration.newlines(), cloopsComponent)
|
||||
);
|
||||
}
|
||||
default -> throw new CommandException(Component.text("Invalid action"));
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,12 +5,17 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
// based off of HBot's supercb command
|
||||
public class CommandBlockCommand extends Command {
|
||||
|
@ -20,8 +25,8 @@ public class CommandBlockCommand extends Command {
|
|||
public CommandBlockCommand () {
|
||||
super(
|
||||
"cb",
|
||||
"Executes a command in the command core and return its output",
|
||||
new String[] {
|
||||
"",
|
||||
"<command>",
|
||||
"..{username}..",
|
||||
"..{uuid}..",
|
||||
|
@ -29,21 +34,70 @@ public class CommandBlockCommand extends Command {
|
|||
"..{uuid{regex}}.."
|
||||
},
|
||||
new String[] { "cmd", "commandblock", "run", "core" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
runCommand(bot, context, context.getString(true, true));
|
||||
final String command = context.getString(true, false);
|
||||
|
||||
if (command.isEmpty()) {
|
||||
return getInfo(bot);
|
||||
}
|
||||
|
||||
try {
|
||||
runCommand(bot, context, command, null);
|
||||
} catch (final PatternSyntaxException e) {
|
||||
throw new CommandException(Component.text(e.toString()));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void runCommand (Bot bot, CommandContext context, String command) {
|
||||
private Component getInfo (final Bot bot) {
|
||||
final Vector3i from = bot.core.from;
|
||||
final Vector3i to = bot.core.to;
|
||||
final Vector3i block = bot.core.block;
|
||||
|
||||
final int layers = Math.max(1, to.getY() - from.getY());
|
||||
|
||||
final StringBuilder commandBuilder = new StringBuilder("/");
|
||||
|
||||
if (bot.serverFeatures.hasEssentials) commandBuilder.append("essentials:");
|
||||
commandBuilder
|
||||
.append("tp ")
|
||||
.append(from.getX())
|
||||
.append(" ")
|
||||
.append(from.getY())
|
||||
.append(" ")
|
||||
.append(from.getZ());
|
||||
|
||||
final String command = commandBuilder.toString();
|
||||
|
||||
return Component.translatable(
|
||||
"commands.cb.info.output",
|
||||
bot.colorPalette.secondary,
|
||||
Component.translatable(
|
||||
"commands.cb.info.size",
|
||||
bot.colorPalette.string,
|
||||
Component.text(256 * layers)
|
||||
),
|
||||
Component.text(layers, bot.colorPalette.string),
|
||||
Component.text(from.toString(), bot.colorPalette.string),
|
||||
Component.text(to.toString(), bot.colorPalette.string),
|
||||
Component.text(block.toString(), bot.colorPalette.string),
|
||||
Component.text(bot.world.currentDimension, bot.colorPalette.string),
|
||||
Component
|
||||
.translatable("commands.cb.info.click_to_teleport", NamedTextColor.GREEN)
|
||||
.hoverEvent(HoverEvent.showText(Component.text(command, bot.colorPalette.secondary)))
|
||||
.clickEvent(ClickEvent.runCommand(command))
|
||||
);
|
||||
}
|
||||
|
||||
private void runCommand (final Bot bot, final CommandContext context, final String command, final PlayerEntry player) {
|
||||
final Matcher userMatcher = USER_PATTERN.matcher(command);
|
||||
final Matcher uuidMatcher = UUID_PATTERN.matcher(command);
|
||||
|
||||
|
@ -51,51 +105,57 @@ public class CommandBlockCommand extends Command {
|
|||
final boolean uuidFound = uuidMatcher.find();
|
||||
|
||||
if (userFound || uuidFound) {
|
||||
Pattern pattern;
|
||||
final Pattern pattern;
|
||||
|
||||
if (userFound) pattern = Pattern.compile(userMatcher.group(1));
|
||||
else pattern = Pattern.compile(uuidMatcher.group(1));
|
||||
|
||||
for (PlayerEntry entry : bot.players.list) {
|
||||
final String username = entry.profile.getName();
|
||||
final String uuid = entry.profile.getIdAsString();
|
||||
synchronized (bot.players.list) {
|
||||
for (final PlayerEntry entry : bot.players.list) {
|
||||
final String username = entry.profile.getName();
|
||||
final String uuid = entry.profile.getIdAsString();
|
||||
|
||||
if (!pattern.matcher(userFound ? username : uuid).matches()) continue;
|
||||
if (!pattern.matcher(userFound ? username : uuid).matches()) continue;
|
||||
|
||||
String replacedCommand;
|
||||
String replacedCommand;
|
||||
|
||||
if (userFound) replacedCommand = new StringBuilder(command).replace(userMatcher.start(), userMatcher.end(), username).toString();
|
||||
else replacedCommand = new StringBuilder(command).replace(uuidMatcher.start(), uuidMatcher.end(), uuid).toString();
|
||||
if (userFound)
|
||||
replacedCommand = new StringBuilder(command).replace(userMatcher.start(), userMatcher.end(), username).toString();
|
||||
else
|
||||
replacedCommand = new StringBuilder(command).replace(uuidMatcher.start(), uuidMatcher.end(), uuid).toString();
|
||||
|
||||
replacedCommand = replacedCommand
|
||||
.replace("{username}", username)
|
||||
.replace("{uuid}", uuid);
|
||||
replacedCommand = replacedCommand
|
||||
.replace("{username}", username)
|
||||
.replace("{uuid}", uuid);
|
||||
|
||||
if (
|
||||
!replacedCommand.contains("{username}") &&
|
||||
!replacedCommand.contains("{uuid}") &&
|
||||
!USER_PATTERN.matcher(username).find() &&
|
||||
!UUID_PATTERN.matcher(username).find()
|
||||
) {
|
||||
runCommand(bot, context, replacedCommand);
|
||||
if (
|
||||
!replacedCommand.contains("{username}") &&
|
||||
!replacedCommand.contains("{uuid}") &&
|
||||
!USER_PATTERN.matcher(username).find() &&
|
||||
!UUID_PATTERN.matcher(username).find()
|
||||
) {
|
||||
runCommand(bot, context, replacedCommand, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (command.contains("{username}") || command.contains("{uuid}")) {
|
||||
for (PlayerEntry entry : bot.players.list) {
|
||||
final String username = entry.profile.getName();
|
||||
final String uuid = entry.profile.getIdAsString();
|
||||
synchronized (bot.players.list) {
|
||||
for (final PlayerEntry entry : bot.players.list) {
|
||||
final String username = entry.profile.getName();
|
||||
final String uuid = entry.profile.getIdAsString();
|
||||
|
||||
final String replacedCommand = command
|
||||
.replace("{username}", username)
|
||||
.replace("{uuid}", uuid);
|
||||
final String replacedCommand = command
|
||||
.replace("{username}", username)
|
||||
.replace("{uuid}", uuid);
|
||||
|
||||
if (
|
||||
!replacedCommand.contains("{username}") &&
|
||||
!replacedCommand.contains("{Uuuid}") &&
|
||||
!USER_PATTERN.matcher(username).find() &&
|
||||
!UUID_PATTERN.matcher(username).find()
|
||||
) {
|
||||
runCommand(bot, context, replacedCommand);
|
||||
if (
|
||||
!replacedCommand.contains("{username}") &&
|
||||
!replacedCommand.contains("{uuid}") &&
|
||||
!USER_PATTERN.matcher(username).find() &&
|
||||
!UUID_PATTERN.matcher(username).find()
|
||||
) {
|
||||
runCommand(bot, context, replacedCommand, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -103,8 +163,42 @@ public class CommandBlockCommand extends Command {
|
|||
|
||||
if (future == null) return;
|
||||
|
||||
future.thenApplyAsync(output -> {
|
||||
context.sendOutput(output);
|
||||
future.thenApply(output -> {
|
||||
if (player == null) context.sendOutput(output);
|
||||
else {
|
||||
final Component component = Component
|
||||
.translatable(
|
||||
"[%s] %s",
|
||||
Component
|
||||
.text(player.profile.getName())
|
||||
.color(NamedTextColor.GRAY)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component
|
||||
.text(player.profile.getName())
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component
|
||||
.text(player.profile.getIdAsString())
|
||||
.color(bot.colorPalette.uuid)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(Component.translatable("commands.generic.click_to_copy_username", NamedTextColor.GREEN))
|
||||
.append(Component.newline())
|
||||
.append(Component.translatable("commands.generic.shift_click_to_insert_uuid", NamedTextColor.GREEN))
|
||||
)
|
||||
)
|
||||
.clickEvent(ClickEvent.copyToClipboard(player.profile.getName()))
|
||||
.insertion(player.profile.getIdAsString()),
|
||||
Component
|
||||
.empty()
|
||||
.append(output)
|
||||
.color(NamedTextColor.WHITE)
|
||||
)
|
||||
.color(NamedTextColor.DARK_GRAY);
|
||||
|
||||
context.sendOutput(component);
|
||||
}
|
||||
|
||||
return output;
|
||||
});
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
|
@ -13,54 +13,83 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
|
||||
public class ConsoleCommand extends Command {
|
||||
public ConsoleCommand() {
|
||||
public ConsoleCommand () {
|
||||
super(
|
||||
"console",
|
||||
"Controls stuff about console",
|
||||
new String[] {
|
||||
"server <server>",
|
||||
"discord <message>",
|
||||
"logtoconsole <true|false>",
|
||||
"printdisconnectedreason <true|false>"
|
||||
},
|
||||
new String[] {},
|
||||
new String[] { "csvr" },
|
||||
TrustLevel.OWNER,
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String action = context.getString(false, true, true);
|
||||
final String action = !context.userInputCommandName.equals(this.name)
|
||||
? "server" // csvr alias (console server), like in the original chomens bot javascript
|
||||
: context.getString(false, true, true);
|
||||
|
||||
switch (action) {
|
||||
case "server" -> {
|
||||
final List<String> servers = new ArrayList<>();
|
||||
|
||||
for (Bot eachBot : bot.bots) {
|
||||
servers.add(eachBot.host + ":" + eachBot.port);
|
||||
for (final Bot eachBot : bot.bots) {
|
||||
servers.add(eachBot.getServerString(true));
|
||||
}
|
||||
|
||||
final String server = context.getString(true, true);
|
||||
|
||||
for (Bot eachBot : bot.bots) {
|
||||
if (server.equalsIgnoreCase("all")) {
|
||||
eachBot.console.consoleServer = "all";
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
try {
|
||||
// servers.find(server => server.toLowerCase().includes(args.join(' '))) in js i guess
|
||||
eachBot.console.consoleServer = servers.stream()
|
||||
.filter(eachServer -> eachServer.toLowerCase().contains(server))
|
||||
.findFirst()
|
||||
.orElse("all");
|
||||
} catch (ArrayIndexOutOfBoundsException e) {
|
||||
throw new CommandException(Component.text("Invalid server: " + server));
|
||||
}
|
||||
if (server.equalsIgnoreCase("all")) {
|
||||
Main.console.consoleServer = "all";
|
||||
return Component.translatable(
|
||||
"commands.console.server.set",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable("commands.console.server.all_servers")
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// servers.find(server => server.toLowerCase().includes(args.join(' '))) in js i guess
|
||||
Main.console.consoleServer = servers.stream()
|
||||
.filter(eachServer -> eachServer.toLowerCase().contains(server))
|
||||
.findFirst()
|
||||
.orElse("all");
|
||||
|
||||
return Component.translatable(
|
||||
"commands.console.server.set",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(Main.console.consoleServer)
|
||||
);
|
||||
} catch (final ArrayIndexOutOfBoundsException e) {
|
||||
throw new CommandException(
|
||||
Component.translatable(
|
||||
"commands.console.server.error.invalid_server",
|
||||
Component.text(server)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
case "discord" -> {
|
||||
if (Main.discord == null || Main.discord.jda == null) {
|
||||
throw new CommandException(Component.translatable("commands.generic.error.discord_disabled"));
|
||||
}
|
||||
|
||||
final String channelId = context.bot.options.discordChannelId;
|
||||
|
||||
if (channelId == null) return null;
|
||||
|
||||
final String message = context.getString(true, true);
|
||||
|
||||
Main.discord.sendMessageInstantly(message, channelId, true);
|
||||
|
||||
return null;
|
||||
}
|
||||
case "logtoconsole" -> {
|
||||
context.checkOverloadArgs(2);
|
||||
|
@ -70,9 +99,12 @@ public class ConsoleCommand extends Command {
|
|||
bot.logger.logToConsole = bool;
|
||||
|
||||
return Component.translatable(
|
||||
"Logging to console is now %s",
|
||||
bool ? Component.text("enabled").color(NamedTextColor.GREEN) : Component.text("disabled").color(NamedTextColor.RED)
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
"commands.console.logtoconsole.set",
|
||||
bot.colorPalette.defaultColor,
|
||||
bool
|
||||
? Component.translatable("commands.generic.enabled", NamedTextColor.GREEN)
|
||||
: Component.translatable("commands.generic.disabled", NamedTextColor.RED)
|
||||
);
|
||||
}
|
||||
case "printdisconnectedreason" -> {
|
||||
context.checkOverloadArgs(2);
|
||||
|
@ -82,9 +114,12 @@ public class ConsoleCommand extends Command {
|
|||
bot.printDisconnectedCause = bool;
|
||||
|
||||
return Component.translatable(
|
||||
"Printing the disconnected cause is now %s",
|
||||
bool ? Component.text("enabled").color(NamedTextColor.GREEN) : Component.text("disabled").color(NamedTextColor.RED)
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
"commands.console.printdisconnectedreason.set",
|
||||
bot.colorPalette.defaultColor,
|
||||
bool
|
||||
? Component.translatable("commands.generic.enabled", NamedTextColor.GREEN)
|
||||
: Component.translatable("commands.generic.disabled", NamedTextColor.RED)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -11,16 +11,14 @@ public class CowsayCommand extends Command {
|
|||
public CowsayCommand () {
|
||||
super(
|
||||
"cowsay",
|
||||
"Moo",
|
||||
new String[] { "<message>" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final String message = context.getString(true, true);
|
||||
|
||||
final CowExecutor cowExecutor = new CowExecutor();
|
||||
|
|
|
@ -5,22 +5,23 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class EchoCommand extends Command {
|
||||
public EchoCommand () {
|
||||
super(
|
||||
"echo",
|
||||
"Makes the bot say a message",
|
||||
new String[] { "<message>" },
|
||||
new String[] { "say" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[] { ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
bot.chat.send(context.getString(true, true));
|
||||
|
|
|
@ -5,27 +5,28 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class EndCommand extends Command {
|
||||
public EndCommand () {
|
||||
super(
|
||||
"end",
|
||||
"End/Reconnects the bot",
|
||||
new String[] { "" },
|
||||
new String[] { "reconnect", "restart" },
|
||||
TrustLevel.TRUSTED,
|
||||
false
|
||||
new String[] { "reconnect" },
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(0);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
bot.session.disconnect("End command");
|
||||
bot.executorService.execute(
|
||||
() -> bot.session.disconnect(I18nUtilities.get("commands.end.disconnect_reason"))
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -5,8 +5,9 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.data.eval.EvalOutput;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.plugins.EvalPlugin;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
|
@ -16,21 +17,21 @@ public class EvalCommand extends Command {
|
|||
public EvalCommand () {
|
||||
super(
|
||||
"eval",
|
||||
"Evaluate JavaScript codes on a Node.JS container running @n8n/vm2",
|
||||
new String[] { "run <code>", "reset" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[]{ ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
if (!bot.eval.connected) throw new CommandException(Component.text("Eval server is not online"));
|
||||
if (!EvalPlugin.connected) throw new CommandException(Component.translatable("commands.eval.error.offline"));
|
||||
|
||||
final String action = context.getString(false, true);
|
||||
final String action = context.getAction();
|
||||
|
||||
switch (action) {
|
||||
case "run" -> {
|
||||
|
@ -38,19 +39,22 @@ public class EvalCommand extends Command {
|
|||
|
||||
final CompletableFuture<EvalOutput> future = bot.eval.run(command);
|
||||
|
||||
future.thenApplyAsync(output -> {
|
||||
if (output.isError()) context.sendOutput(Component.text(output.output()).color(NamedTextColor.RED));
|
||||
else context.sendOutput(Component.text(output.output()));
|
||||
// it returns null when the eval server isn't online, even though we have already checked,
|
||||
// i'm just fixing the warning here
|
||||
if (future == null) return null;
|
||||
|
||||
return output;
|
||||
future.thenApply(result -> {
|
||||
if (result.isError()) context.sendOutput(Component.text(result.output(), NamedTextColor.RED));
|
||||
else context.sendOutput(Component.text(result.output()));
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
case "reset" -> {
|
||||
bot.eval.reset();
|
||||
|
||||
return Component.text("Reset the eval worker").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
EvalPlugin.reset();
|
||||
return Component.translatable("commands.eval.reset", bot.colorPalette.defaultColor);
|
||||
}
|
||||
default -> throw new CommandException(Component.text("Invalid action"));
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -1,96 +1,124 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.FilteredPlayer;
|
||||
import me.chayapak1.chomens_bot.plugins.FilterPlugin;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.command.*;
|
||||
import me.chayapak1.chomens_bot.data.filter.PlayerFilter;
|
||||
import me.chayapak1.chomens_bot.plugins.DatabasePlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.PlayerFilterPlugin;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
public class FilterCommand extends Command {
|
||||
public FilterCommand () {
|
||||
super(
|
||||
"filter",
|
||||
"Filter players",
|
||||
new String[] {
|
||||
"add <player>",
|
||||
"-ignorecase add <player>",
|
||||
"-regex add <player>",
|
||||
"-ignorecase -regex add <player>",
|
||||
"add <player> [reason]",
|
||||
"-ignorecase add <player> [reason]",
|
||||
"-regex add <player> [reason]",
|
||||
"remove <index>",
|
||||
"clear",
|
||||
"list"
|
||||
},
|
||||
new String[] { "filterplayer", "ban", "blacklist" },
|
||||
TrustLevel.OWNER,
|
||||
false
|
||||
TrustLevel.ADMIN
|
||||
);
|
||||
}
|
||||
|
||||
// most of these codes are from cloop and greplog
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
boolean ignoreCase = false;
|
||||
boolean regex = false;
|
||||
final List<String> flags = context.getFlags(true, CommonFlags.IGNORE_CASE, CommonFlags.REGEX);
|
||||
|
||||
String action = context.getString(false, true);
|
||||
final boolean ignoreCase = flags.contains(CommonFlags.IGNORE_CASE);
|
||||
final boolean regex = flags.contains(CommonFlags.REGEX);
|
||||
|
||||
// run 2 times. for example `*filter -ignorecase -regex add test` will be both accepted
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (action.equals("-ignorecase")) {
|
||||
ignoreCase = true;
|
||||
action = context.getString(false, true);
|
||||
} else if (action.equals("-regex")) {
|
||||
regex = true;
|
||||
action = context.getString(false, true);
|
||||
}
|
||||
}
|
||||
|
||||
final Gson gson = new Gson();
|
||||
final String action = context.getString(false, true, true);
|
||||
|
||||
switch (action) {
|
||||
case "add" -> {
|
||||
final String player = context.getString(true, true);
|
||||
final String player = context.getString(false, true);
|
||||
final String reason = context.getString(true, false);
|
||||
|
||||
bot.filter.add(player, regex, ignoreCase);
|
||||
return Component.translatable(
|
||||
"Added %s to the filters",
|
||||
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
if (
|
||||
PlayerFilterPlugin.localList.stream()
|
||||
.map(PlayerFilter::playerName)
|
||||
.toList()
|
||||
.contains(player)
|
||||
) {
|
||||
throw new CommandException(
|
||||
Component.translatable(
|
||||
"commands.filter.add.error.already_exists",
|
||||
Component.text(player)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if (regex) {
|
||||
// try validating the regex
|
||||
try {
|
||||
Pattern.compile(player);
|
||||
} catch (final PatternSyntaxException e) {
|
||||
throw new CommandException(
|
||||
Component.translatable(
|
||||
"commands.filter.error.invalid_regex",
|
||||
Component.text(e.toString())
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> bot.playerFilter.add(player, reason, regex, ignoreCase));
|
||||
|
||||
if (reason.isEmpty()) {
|
||||
return Component.translatable(
|
||||
"commands.filter.add.no_reason",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(player, bot.colorPalette.username)
|
||||
);
|
||||
} else {
|
||||
return Component.translatable(
|
||||
"commands.filter.add.reason",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(player, bot.colorPalette.username),
|
||||
Component.text(reason, bot.colorPalette.string)
|
||||
);
|
||||
}
|
||||
}
|
||||
case "remove" -> {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
try {
|
||||
final int index = context.getInteger(true);
|
||||
final int index = context.getInteger(true);
|
||||
|
||||
final FilteredPlayer removed = bot.filter.remove(index);
|
||||
try {
|
||||
final PlayerFilter player = PlayerFilterPlugin.localList.get(index);
|
||||
|
||||
if (player == null) throw new IllegalArgumentException();
|
||||
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> bot.playerFilter.remove(player.playerName()));
|
||||
|
||||
return Component.translatable(
|
||||
"Removed %s from the filters",
|
||||
Component.text(removed.playerName).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
} catch (IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) {
|
||||
throw new CommandException(Component.text("Invalid index"));
|
||||
"commands.filter.remove.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(player.playerName(), bot.colorPalette.username)
|
||||
);
|
||||
} catch (final IndexOutOfBoundsException | IllegalArgumentException | NullPointerException e) {
|
||||
throw new CommandException(Component.translatable("commands.generic.error.invalid_index"));
|
||||
}
|
||||
}
|
||||
case "clear" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
bot.filter.clear();
|
||||
return Component.text("Cleared the filter").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(bot.playerFilter::clear);
|
||||
return Component.translatable("commands.filter.clear.output", bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "list" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
@ -98,45 +126,66 @@ public class FilterCommand extends Command {
|
|||
final List<Component> filtersComponents = new ArrayList<>();
|
||||
|
||||
int index = 0;
|
||||
for (JsonElement playerElement : FilterPlugin.filteredPlayers) {
|
||||
final FilteredPlayer player = gson.fromJson(playerElement, FilteredPlayer.class);
|
||||
|
||||
for (final PlayerFilter player : PlayerFilterPlugin.localList) {
|
||||
Component options = Component.empty().color(NamedTextColor.DARK_GRAY);
|
||||
|
||||
if (player.ignoreCase || player.regex) {
|
||||
if (player.ignoreCase() || player.regex()) {
|
||||
final List<Component> args = new ArrayList<>();
|
||||
|
||||
if (player.ignoreCase) args.add(Component.text("ignore case"));
|
||||
if (player.regex) args.add(Component.text("regex"));
|
||||
if (player.ignoreCase()) args.add(Component.translatable("commands.filter.list.ignore_case"));
|
||||
if (player.regex()) args.add(Component.translatable("commands.filter.list.regex"));
|
||||
|
||||
options = options.append(Component.text("("));
|
||||
options = options.append(Component.join(JoinConfiguration.commas(true), args).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)));
|
||||
options = options.append(Component.text(")"));
|
||||
options = options
|
||||
.append(Component.text("("))
|
||||
.append(
|
||||
Component
|
||||
.join(
|
||||
JoinConfiguration.commas(true),
|
||||
args
|
||||
)
|
||||
.color(bot.colorPalette.string)
|
||||
)
|
||||
.append(Component.text(")"))
|
||||
.append(Component.space());
|
||||
}
|
||||
|
||||
if (!player.reason().isEmpty()) {
|
||||
options = options
|
||||
.append(Component.text("("))
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.filter.list.reason",
|
||||
NamedTextColor.GRAY,
|
||||
Component.text(player.reason(), bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
.append(Component.text(")"));
|
||||
}
|
||||
|
||||
filtersComponents.add(
|
||||
Component.translatable(
|
||||
"%s › %s %s",
|
||||
Component.text(index).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
|
||||
Component.text(player.playerName).color(ColorUtilities.getColorByString(bot.config.colorPalette.username)),
|
||||
NamedTextColor.DARK_GRAY,
|
||||
Component.text(index, bot.colorPalette.number),
|
||||
Component.text(player.playerName(), bot.colorPalette.username),
|
||||
options
|
||||
).color(NamedTextColor.DARK_GRAY)
|
||||
)
|
||||
);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Filtered players ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(FilterPlugin.filteredPlayers.size()).color(NamedTextColor.GRAY))
|
||||
.append(Component.text(")").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.translatable("commands.filter.list.filtered_players_text", NamedTextColor.GREEN))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(PlayerFilterPlugin.localList.size(), NamedTextColor.GRAY))
|
||||
.append(Component.text(")", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.join(JoinConfiguration.newlines(), filtersComponents)
|
||||
);
|
||||
}
|
||||
default -> throw new CommandException(Component.text("Invalid action"));
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,91 +1,122 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.plugins.PlayersPersistentDataPlugin;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.plugins.DatabasePlugin;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.Optional;
|
||||
|
||||
public class FindAltsCommand extends Command {
|
||||
public FindAltsCommand() {
|
||||
// we allow both, since the flag used to be `allserver`
|
||||
private static final String ALL_SERVER_FLAG = "allserver";
|
||||
private static final String ALL_SERVERS_FLAG = "allservers";
|
||||
|
||||
private static final int LIMIT = 200;
|
||||
|
||||
public FindAltsCommand () {
|
||||
super(
|
||||
"findalts",
|
||||
"Finds players with the same IP address",
|
||||
new String[] { "<player>", "<ip>" },
|
||||
new String[] { "-allservers <player|ip>", "<player|ip>" },
|
||||
new String[] { "alts", "sameip" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[] { ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws Exception {
|
||||
public Component execute (final CommandContext context) throws Exception {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
if (Main.database == null)
|
||||
throw new CommandException(Component.translatable("commands.generic.error.database_disabled"));
|
||||
|
||||
Main.database.checkOverloaded();
|
||||
|
||||
final List<String> flags = context.getFlags(true, ALL_SERVER_FLAG, ALL_SERVERS_FLAG);
|
||||
|
||||
final boolean allServer = flags.contains(ALL_SERVER_FLAG) || flags.contains(ALL_SERVERS_FLAG);
|
||||
|
||||
final String player = context.getString(true, true);
|
||||
|
||||
final PlayerEntry playerEntry = bot.players.getEntry(player);
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> {
|
||||
final PlayerEntry playerInTheServer = bot.players.getEntry(player);
|
||||
|
||||
if (playerEntry == null) return handle(bot, player, true, player);
|
||||
else {
|
||||
final CompletableFuture<String> future = bot.players.getPlayerIP(playerEntry);
|
||||
final String ipFromUsername;
|
||||
|
||||
if (future == null) return null;
|
||||
if (playerInTheServer == null || playerInTheServer.persistingData.ip == null)
|
||||
ipFromUsername = bot.playersDatabase.getPlayerIP(player);
|
||||
else ipFromUsername = playerInTheServer.persistingData.ip;
|
||||
|
||||
future.thenApplyAsync(targetIP -> {
|
||||
context.sendOutput(handle(bot, targetIP, false, player));
|
||||
|
||||
return targetIP;
|
||||
});
|
||||
}
|
||||
if (ipFromUsername == null) {
|
||||
context.sendOutput(handle(bot, player, player, allServer));
|
||||
} else {
|
||||
context.sendOutput(handle(bot, ipFromUsername, player, allServer));
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private Component handle (Bot bot, String targetIP, boolean argumentIsIP, String player) {
|
||||
final Stream<String> matches = PlayersPersistentDataPlugin.playersObject.deepCopy().entrySet() // is calling deepCopy necessary?
|
||||
.stream()
|
||||
.filter(
|
||||
entry -> {
|
||||
final JsonObject ipsObject = entry
|
||||
.getValue().getAsJsonObject().getAsJsonObject("ips");
|
||||
private Component handle (final Bot bot, final String targetIP, final String player, final boolean allServer) {
|
||||
final Map<String, JsonNode> altsMap = bot.playersDatabase.findPlayerAlts(targetIP, allServer, LIMIT);
|
||||
|
||||
if (ipsObject == null) return false;
|
||||
final Component playerComponent = Component.text(player, bot.colorPalette.username);
|
||||
|
||||
final JsonElement currentServerIP = ipsObject.get(bot.host + ":" + bot.port);
|
||||
|
||||
if (currentServerIP == null) return false;
|
||||
|
||||
return currentServerIP.getAsString().equals(targetIP);
|
||||
}
|
||||
)
|
||||
.map(Map.Entry::getKey);
|
||||
final boolean isIP = targetIP.equals(player);
|
||||
|
||||
Component component = Component
|
||||
.translatable("Possible alts for the %s %s:")
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
|
||||
.translatable("commands.findalts.output", bot.colorPalette.defaultColor)
|
||||
.arguments(
|
||||
Component.text(argumentIsIP ? "IP" : "player"),
|
||||
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
Component.translatable(isIP ? "commands.findalts.ip" : "commands.findalts.player"),
|
||||
isIP ?
|
||||
playerComponent :
|
||||
Component.translatable(
|
||||
"%s (%s)",
|
||||
playerComponent,
|
||||
Component
|
||||
.text(targetIP)
|
||||
.color(bot.colorPalette.number)
|
||||
)
|
||||
)
|
||||
.appendNewline();
|
||||
|
||||
final List<String> sorted = altsMap.entrySet().stream()
|
||||
.limit(200) // only find 200 alts because more than this is simply too many
|
||||
.sorted((a, b) -> {
|
||||
final JsonNode aTimeNode = Optional.ofNullable(a.getValue().get("lastSeen"))
|
||||
.map(node -> node.get("time"))
|
||||
.orElse(null);
|
||||
final JsonNode bTimeNode = Optional.ofNullable(b.getValue().get("lastSeen"))
|
||||
.map(node -> node.get("time"))
|
||||
.orElse(null);
|
||||
|
||||
if (aTimeNode == null && bTimeNode == null) return 0;
|
||||
if (aTimeNode == null) return 1;
|
||||
if (bTimeNode == null) return -1;
|
||||
|
||||
return Long.compare(bTimeNode.asLong(), aTimeNode.asLong());
|
||||
})
|
||||
.map(Map.Entry::getKey)
|
||||
.toList();
|
||||
|
||||
int i = 0;
|
||||
for (String name : matches.toList()) {
|
||||
for (final String username : sorted) {
|
||||
component = component
|
||||
.append(
|
||||
Component
|
||||
.text(name)
|
||||
.color((i++ & 1) == 0 ? ColorUtilities.getColorByString(bot.config.colorPalette.primary) : ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
||||
.text(username)
|
||||
.color((i++ & 1) == 0 ? bot.colorPalette.primary : bot.colorPalette.secondary)
|
||||
)
|
||||
.appendSpace();
|
||||
}
|
||||
|
|
|
@ -1,86 +1,65 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.*;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GrepLogCommand extends Command {
|
||||
private Thread thread;
|
||||
|
||||
public GrepLogCommand() {
|
||||
public GrepLogCommand () {
|
||||
super(
|
||||
"greplog",
|
||||
"Queries the bot's logs",
|
||||
new String[] { "<input>", "...-ignorecase...", "...-regex...", "stop" },
|
||||
new String[] { "<input>", "-ignorecase ...", "-regex ...", "stop" },
|
||||
new String[] { "logquery", "findlog" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
if (bot.discord.jda == null) throw new CommandException(Component.text("The bot's Discord integration has to be enabled to use the command."));
|
||||
|
||||
boolean ignoreCase = false;
|
||||
boolean regex = false;
|
||||
|
||||
String firstInput = context.getString(false, true);
|
||||
|
||||
// run 2 times. for example `*greplog -ignorecase -regex test` will be both accepted
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (firstInput.equals("-ignorecase")) {
|
||||
ignoreCase = true;
|
||||
firstInput = context.getString(false, true);
|
||||
} else if (firstInput.equals("-regex")) {
|
||||
regex = true;
|
||||
firstInput = context.getString(false, true);
|
||||
}
|
||||
if (Main.discord == null || Main.discord.jda == null) {
|
||||
throw new CommandException(Component.translatable("commands.generic.error.discord_disabled"));
|
||||
}
|
||||
|
||||
// interesting code
|
||||
final String input = (firstInput + " " + context.getString(true, false)).trim();
|
||||
final List<String> flags = context.getFlags(true, CommonFlags.IGNORE_CASE, CommonFlags.REGEX);
|
||||
|
||||
if (input.equals("stop")) {
|
||||
if (thread == null) throw new CommandException(Component.text("There is no query process running"));
|
||||
final boolean ignoreCase = flags.contains(CommonFlags.IGNORE_CASE);
|
||||
final boolean regex = flags.contains(CommonFlags.REGEX);
|
||||
|
||||
final String input = context.getString(true, true);
|
||||
|
||||
if (input.equalsIgnoreCase("stop")) {
|
||||
if (thread == null) throw new CommandException(Component.translatable("commands.greplog.error.not_running"));
|
||||
|
||||
bot.grepLog.running = false;
|
||||
bot.grepLog.pattern = null;
|
||||
|
||||
thread.interrupt(); // ? should i interrupt it this way?
|
||||
|
||||
thread = null;
|
||||
|
||||
return Component.text("Stopped querying the logs").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.greplog.stopped", bot.colorPalette.defaultColor);
|
||||
}
|
||||
|
||||
if (thread != null) throw new CommandException(Component.text("Another query is already running"));
|
||||
if (thread != null) throw new CommandException(Component.translatable("commands.greplog.error.already_running"));
|
||||
|
||||
context.sendOutput(
|
||||
Component
|
||||
.translatable("Started querying the logs for %s")
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
|
||||
.translatable("commands.greplog.started", bot.colorPalette.defaultColor)
|
||||
.arguments(
|
||||
Component
|
||||
.text(input)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
||||
Component.text(input, bot.colorPalette.string)
|
||||
)
|
||||
);
|
||||
|
||||
final boolean finalIgnoreCase = ignoreCase;
|
||||
final boolean finalRegex = regex;
|
||||
|
||||
thread = new Thread(() -> {
|
||||
try {
|
||||
bot.grepLog.search(context, input, finalIgnoreCase, finalRegex);
|
||||
} catch (CommandException e) {
|
||||
bot.grepLog.search(context, input, ignoreCase, regex);
|
||||
} catch (final CommandException e) {
|
||||
context.sendOutput(e.message.color(NamedTextColor.RED));
|
||||
}
|
||||
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.command.contexts.ConsoleCommandContext;
|
||||
import me.chayapak1.chomens_bot.plugins.CommandHandlerPlugin;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
@ -21,133 +22,163 @@ public class HelpCommand extends Command {
|
|||
public HelpCommand () {
|
||||
super(
|
||||
"help",
|
||||
"Shows a command list or usage for a command",
|
||||
new String[] { "[command]" },
|
||||
new String[] { "heko", "cmds", "commands" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
private CommandContext context;
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
this.context = context;
|
||||
|
||||
final String commandName = context.getString(false, false);
|
||||
|
||||
if (commandName.isEmpty()) {
|
||||
return sendCommandList();
|
||||
if (commandName.isBlank()) {
|
||||
return getCommandList(context);
|
||||
} else {
|
||||
return sendUsages(context, commandName);
|
||||
return getUsages(context, commandName);
|
||||
}
|
||||
}
|
||||
|
||||
public Component sendCommandList () throws CommandException {
|
||||
final List<Component> list = new ArrayList<>();
|
||||
list.addAll(getCommandListByTrustLevel(TrustLevel.PUBLIC));
|
||||
list.addAll(getCommandListByTrustLevel(TrustLevel.TRUSTED));
|
||||
list.addAll(getCommandListByTrustLevel(TrustLevel.OWNER));
|
||||
public Component getCommandList (final CommandContext context) {
|
||||
final List<Component> list = new ObjectArrayList<>();
|
||||
|
||||
for (final TrustLevel level : TrustLevel.values()) {
|
||||
list.addAll(getCommandListByTrustLevel(context, level));
|
||||
}
|
||||
|
||||
final Component trustLevels = Component.join(
|
||||
JoinConfiguration.spaces(),
|
||||
Arrays.stream(TrustLevel.values())
|
||||
.map(level -> level.component)
|
||||
.toList()
|
||||
);
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Commands ").color(NamedTextColor.GRAY))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(list.size()).color(NamedTextColor.GREEN))
|
||||
.append(Component.text(") ").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("Public ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text("Trusted ").color(NamedTextColor.RED))
|
||||
.append(Component.text("Owner").color(NamedTextColor.DARK_RED))
|
||||
.append(Component.text(") - ").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), list));
|
||||
.append(Component.translatable("commands.help.commands_text", NamedTextColor.GRAY))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(list.size(), NamedTextColor.GREEN))
|
||||
.append(Component.text(") ", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.translatable("%s", trustLevels))
|
||||
.append(Component.text(") - ", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.space()), list));
|
||||
}
|
||||
|
||||
public List<Component> getCommandListByTrustLevel(TrustLevel trustLevel) throws CommandException {
|
||||
final List<Component> list = new ArrayList<>();
|
||||
public List<Component> getCommandListByTrustLevel (final CommandContext context, final TrustLevel trustLevel) {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
List<String> commandNames = new ArrayList<>();
|
||||
final List<Component> list = new ObjectArrayList<>();
|
||||
|
||||
for (Command command : CommandHandlerPlugin.commands) {
|
||||
if (command.trustLevel != trustLevel || command.consoleOnly) continue;
|
||||
final List<String> commandNames = new ObjectArrayList<>();
|
||||
|
||||
for (final Command command : CommandHandlerPlugin.COMMANDS) {
|
||||
if (command.trustLevel != trustLevel || (command.consoleOnly && !(context instanceof ConsoleCommandContext)))
|
||||
continue;
|
||||
|
||||
commandNames.add(command.name);
|
||||
}
|
||||
|
||||
Collections.sort(commandNames);
|
||||
|
||||
for (String name : commandNames) {
|
||||
for (final String name : commandNames) {
|
||||
final String clickSuggestion = context.prefix + name; // *command
|
||||
final String insertionSuggestion = context.prefix + this.name + " " + name; // *help <command>
|
||||
list.add(
|
||||
Component
|
||||
.text(name)
|
||||
.color(getColorByTrustLevel(trustLevel))
|
||||
.color(trustLevel.component.color())
|
||||
.clickEvent(
|
||||
ClickEvent.suggestCommand(clickSuggestion)
|
||||
)
|
||||
.insertion(insertionSuggestion)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
sendUsages(context, name)
|
||||
Component.empty()
|
||||
.color(NamedTextColor.GREEN)
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.help.hover.click_to_command",
|
||||
Component.text(clickSuggestion, bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.help.hover.shift_click_to_help_command",
|
||||
Component.text(insertionSuggestion, bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
// there are too many commands and having hover being the usages will make the command length > 32767 :(
|
||||
/* .hoverEvent(
|
||||
HoverEvent.showText(
|
||||
getUsages(context, name)
|
||||
)
|
||||
) */
|
||||
);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
public NamedTextColor getColorByTrustLevel (TrustLevel trustLevel) {
|
||||
return switch (trustLevel) {
|
||||
case PUBLIC -> NamedTextColor.GREEN;
|
||||
case TRUSTED -> NamedTextColor.RED;
|
||||
case OWNER -> NamedTextColor.DARK_RED;
|
||||
};
|
||||
}
|
||||
|
||||
public Component sendUsages (CommandContext context, String commandName) throws CommandException {
|
||||
public Component getUsages (final CommandContext context, final String commandName) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String prefix = context.prefix;
|
||||
|
||||
for (Command command : CommandHandlerPlugin.commands) {
|
||||
if (!command.name.equalsIgnoreCase(commandName) && !Arrays.stream(command.aliases).toList().contains(commandName.toLowerCase())) continue;
|
||||
for (final Command command : CommandHandlerPlugin.COMMANDS) {
|
||||
if (
|
||||
!command.name.equalsIgnoreCase(commandName) &&
|
||||
!Arrays.stream(command.aliases).toList().contains(commandName.toLowerCase())
|
||||
) continue;
|
||||
|
||||
final String actualCommandName = command.name.toLowerCase();
|
||||
final List<Component> usages = new ArrayList<>();
|
||||
final List<Component> usages = new ObjectArrayList<>();
|
||||
|
||||
usages.add(
|
||||
Component.empty()
|
||||
.append(Component.text(prefix + actualCommandName).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)))
|
||||
.append(Component.text(
|
||||
(command.aliases.length > 0 && !command.aliases[0].isEmpty()) ?
|
||||
" (" + String.join(", ", command.aliases) + ")" :
|
||||
""
|
||||
).color(NamedTextColor.WHITE))
|
||||
.append(Component.text(" - " + command.description)).color(NamedTextColor.GRAY)
|
||||
.color(NamedTextColor.GRAY)
|
||||
.append(Component.text(prefix + actualCommandName, bot.colorPalette.secondary))
|
||||
.append(
|
||||
Component
|
||||
.text(
|
||||
(command.aliases.length > 0 && !command.aliases[0].isEmpty()) ?
|
||||
" (" + String.join(", ", command.aliases) + ")" :
|
||||
"",
|
||||
NamedTextColor.WHITE
|
||||
)
|
||||
)
|
||||
.append(Component.text(" - "))
|
||||
.append(
|
||||
Component.translatable(
|
||||
String.format(
|
||||
"commands.%s.description",
|
||||
actualCommandName
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
usages.add(
|
||||
Component.empty()
|
||||
.append(Component.text("Trust level: ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text(command.trustLevel.name()).color(NamedTextColor.YELLOW))
|
||||
.append(Component.translatable("commands.help.trust_level", NamedTextColor.GREEN))
|
||||
.append(
|
||||
command.trustLevel.component
|
||||
.append(Component.text(" - "))
|
||||
.append(Component.text(command.trustLevel.level))
|
||||
)
|
||||
);
|
||||
|
||||
for (String usage : command.usages) {
|
||||
for (final String usage : command.usages) {
|
||||
Component usageComponent = Component.empty()
|
||||
.append(Component.text(prefix + actualCommandName).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)))
|
||||
.append(Component.text(prefix + actualCommandName, bot.colorPalette.secondary))
|
||||
.append(Component.text(" "));
|
||||
|
||||
if (command.trustLevel == TrustLevel.TRUSTED) {
|
||||
usageComponent = usageComponent
|
||||
.append(Component.text("<hash>"))
|
||||
.append(Component.space())
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.string));
|
||||
} else if (command.trustLevel == TrustLevel.OWNER) {
|
||||
usageComponent = usageComponent
|
||||
.append(Component.text("<ownerHash>"))
|
||||
.append(Component.space())
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.string));
|
||||
}
|
||||
|
||||
usageComponent = usageComponent.append(Component.text(usage).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)));
|
||||
usageComponent = usageComponent.append(Component.text(usage, bot.colorPalette.string));
|
||||
|
||||
usages.add(usageComponent);
|
||||
}
|
||||
|
@ -155,6 +186,6 @@ public class HelpCommand extends Command {
|
|||
return Component.join(JoinConfiguration.separator(Component.newline()), usages);
|
||||
}
|
||||
|
||||
throw new CommandException(Component.text("Unknown command"));
|
||||
throw new CommandException(Component.translatable("commands.help.error.unknown_command"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,75 +1,99 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.plugins.DatabasePlugin;
|
||||
import me.chayapak1.chomens_bot.plugins.IPFilterPlugin;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class IPFilterCommand extends Command {
|
||||
public IPFilterCommand() {
|
||||
public IPFilterCommand () {
|
||||
super(
|
||||
"ipfilter",
|
||||
"Filter IPs",
|
||||
new String[] {
|
||||
"add <ip>",
|
||||
"add <ip> [reason]",
|
||||
"remove <index>",
|
||||
"clear",
|
||||
"list"
|
||||
},
|
||||
new String[] { "filterip", "banip", "ipban" },
|
||||
TrustLevel.OWNER,
|
||||
false
|
||||
TrustLevel.ADMIN
|
||||
);
|
||||
}
|
||||
|
||||
// most of these codes are from cloop and greplog
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String action = context.getString(false, true, true);
|
||||
final String action = context.getAction();
|
||||
|
||||
switch (action) {
|
||||
case "add" -> {
|
||||
final String ip = context.getString(true, true);
|
||||
final String ip = context.getString(false, true);
|
||||
final String reason = context.getString(true, false);
|
||||
|
||||
bot.ipFilter.add(ip);
|
||||
return Component.translatable(
|
||||
"Added %s to the filters",
|
||||
Component.text(ip).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
if (IPFilterPlugin.localList.containsKey(ip)) {
|
||||
throw new CommandException(
|
||||
Component.translatable(
|
||||
"commands.ipfilter.add.error.already_exists",
|
||||
Component.text(ip)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> bot.ipFilter.add(ip, reason));
|
||||
|
||||
if (reason.isEmpty()) {
|
||||
return Component.translatable(
|
||||
"commands.filter.add.no_reason",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(ip, bot.colorPalette.username)
|
||||
);
|
||||
} else {
|
||||
return Component.translatable(
|
||||
"commands.filter.add.reason",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(ip, bot.colorPalette.username),
|
||||
Component.text(reason, bot.colorPalette.string)
|
||||
);
|
||||
}
|
||||
}
|
||||
case "remove" -> {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
try {
|
||||
final int index = context.getInteger(true);
|
||||
final int index = context.getInteger(true);
|
||||
|
||||
final String removed = bot.ipFilter.remove(index);
|
||||
try {
|
||||
final String targetIP = new ArrayList<>(IPFilterPlugin.localList.keySet()).get(index);
|
||||
|
||||
if (targetIP == null) throw new IllegalArgumentException();
|
||||
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> bot.ipFilter.remove(targetIP));
|
||||
|
||||
return Component.translatable(
|
||||
"Removed %s from the filters",
|
||||
Component.text(removed).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
} catch (IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) {
|
||||
throw new CommandException(Component.text("Invalid index"));
|
||||
"commands.ipfilter.remove.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(targetIP, bot.colorPalette.username)
|
||||
);
|
||||
} catch (final IndexOutOfBoundsException | IllegalArgumentException | NullPointerException e) {
|
||||
throw new CommandException(Component.translatable("commands.generic.error.invalid_index"));
|
||||
}
|
||||
}
|
||||
case "clear" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
bot.ipFilter.clear();
|
||||
return Component.text("Cleared the filter").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(bot.ipFilter::clear);
|
||||
return Component.translatable("commands.ipfilter.clear.output", bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "list" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
@ -77,31 +101,49 @@ public class IPFilterCommand extends Command {
|
|||
final List<Component> filtersComponents = new ArrayList<>();
|
||||
|
||||
int index = 0;
|
||||
for (JsonElement playerElement : IPFilterPlugin.filteredIPs) {
|
||||
for (final Map.Entry<String, String> entry : IPFilterPlugin.localList.entrySet()) {
|
||||
final String ip = entry.getKey();
|
||||
final String reason = entry.getValue();
|
||||
|
||||
Component reasonComponent = Component.empty().color(NamedTextColor.DARK_GRAY);
|
||||
|
||||
if (!reason.isEmpty()) {
|
||||
reasonComponent = reasonComponent
|
||||
.append(Component.text("("))
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.ipfilter.list.reason",
|
||||
NamedTextColor.GRAY,
|
||||
Component.text(reason, bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
.append(Component.text(")"));
|
||||
}
|
||||
|
||||
filtersComponents.add(
|
||||
Component.translatable(
|
||||
"%s › %s",
|
||||
Component.text(index).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
|
||||
Component.text(playerElement.getAsString()).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(NamedTextColor.DARK_GRAY)
|
||||
"%s › %s %s",
|
||||
NamedTextColor.DARK_GRAY,
|
||||
Component.text(index, bot.colorPalette.number),
|
||||
Component.text(ip, bot.colorPalette.username),
|
||||
reasonComponent
|
||||
)
|
||||
);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Filtered IPs ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(IPFilterPlugin.filteredIPs.size()).color(NamedTextColor.GRAY))
|
||||
.append(Component.text(")").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.translatable("commands.ipfilter.list.filtered_ips_text", NamedTextColor.GREEN))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(IPFilterPlugin.localList.size(), NamedTextColor.GRAY))
|
||||
.append(Component.text(")", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.join(JoinConfiguration.newlines(), filtersComponents)
|
||||
);
|
||||
}
|
||||
default -> {
|
||||
throw new CommandException(Component.text("Invalid action"));
|
||||
}
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,8 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.util.StringUtilities;
|
||||
import me.chayapak1.chomens_bot.util.TimeUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
|
@ -15,6 +16,7 @@ import net.kyori.adventure.text.format.TextColor;
|
|||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.MemoryUsage;
|
||||
|
@ -23,56 +25,69 @@ import java.net.InetAddress;
|
|||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.FileChannel;
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.ZoneId;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class InfoCommand extends Command {
|
||||
public static final String ORIGINAL_REPOSITORY_URL = "https://code.chipmunk.land/ChomeNS/chomens-bot-java";
|
||||
|
||||
public static final Properties BUILD_INFO = new Properties();
|
||||
|
||||
static {
|
||||
try (final InputStream input = ClassLoader.getSystemClassLoader().getResourceAsStream("application.properties")) {
|
||||
BUILD_INFO.load(input);
|
||||
} catch (final IOException ignored) { }
|
||||
}
|
||||
|
||||
public InfoCommand () {
|
||||
super(
|
||||
"info",
|
||||
"Shows an info about various things",
|
||||
new String[] {
|
||||
"",
|
||||
"<creator>",
|
||||
"<discord>",
|
||||
"<server>",
|
||||
"<botuser>",
|
||||
"<uptime>"
|
||||
"creator",
|
||||
"discord",
|
||||
"server",
|
||||
"botuser",
|
||||
"botlogintime",
|
||||
"uptime"
|
||||
},
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
new String[] { "creator", "discord", "botuser", "botlogintime", "uptime" },
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String action = context.getString(false, false, true);
|
||||
final String action = !context.userInputCommandName.equalsIgnoreCase(this.name) // if the input command is not `info`
|
||||
? context.userInputCommandName.toLowerCase() // use that as the action (e.g. "discord", "creator")
|
||||
: context.getString(false, false, true); // else just take the argument of `info`
|
||||
|
||||
switch (action) {
|
||||
case "creator" -> {
|
||||
return Component.empty()
|
||||
.append(Component.text("ChomeNS Bot ").color(ColorUtilities.getColorByString(bot.config.colorPalette.primary)))
|
||||
.append(Component.text("is created by ").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor)))
|
||||
.append(Component.text("chayapak").color(ColorUtilities.getColorByString(bot.config.colorPalette.ownerName)));
|
||||
return Component.translatable(
|
||||
"commands.info.creator.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text("ChomeNS Bot", bot.colorPalette.primary),
|
||||
Component.text("chayapak", bot.colorPalette.ownerName)
|
||||
);
|
||||
}
|
||||
case "discord" -> {
|
||||
final String link = bot.config.discord.inviteLink;
|
||||
return Component.empty()
|
||||
.append(Component.text("The Discord invite is ").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor)))
|
||||
.append(
|
||||
Component
|
||||
.text(link)
|
||||
.clickEvent(ClickEvent.openUrl(link))
|
||||
.color(NamedTextColor.BLUE)
|
||||
);
|
||||
|
||||
return Component.translatable(
|
||||
"commands.info.discord.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component
|
||||
.text(link, NamedTextColor.BLUE)
|
||||
.clickEvent(ClickEvent.openUrl(link))
|
||||
);
|
||||
}
|
||||
case "server" -> {
|
||||
// totallynotskidded™ from extras' serverinfo
|
||||
|
@ -84,10 +99,10 @@ public class InfoCommand extends Command {
|
|||
final StringBuilder builder = new StringBuilder();
|
||||
|
||||
try {
|
||||
RandomAccessFile file = new RandomAccessFile("/proc/cpuinfo", "r");
|
||||
FileChannel channel = file.getChannel();
|
||||
final RandomAccessFile file = new RandomAccessFile("/proc/cpuinfo", "r");
|
||||
final FileChannel channel = file.getChannel();
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); // 1 MB buffer
|
||||
final ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024); // 1 MB buffer
|
||||
long bytesRead = channel.read(buffer);
|
||||
|
||||
while (bytesRead != -1) {
|
||||
|
@ -103,50 +118,50 @@ public class InfoCommand extends Command {
|
|||
|
||||
channel.close();
|
||||
file.close();
|
||||
} catch (IOException ignored) {}
|
||||
} catch (final IOException ignored) { }
|
||||
|
||||
final TextColor color = ColorUtilities.getColorByString(bot.config.colorPalette.string);
|
||||
final TextColor color = bot.colorPalette.string;
|
||||
|
||||
final String[] lines = builder.toString().split("\n");
|
||||
final Optional<String> modelName = Arrays.stream(lines)
|
||||
.filter(line -> line.startsWith("model name"))
|
||||
.findFirst();
|
||||
final Component cpuModel = modelName
|
||||
.map(s -> Component.text(s.split("\t: ")[1]).color(color))
|
||||
.orElseGet(() -> Component.text("N/A").color(color));
|
||||
.map(s -> Component.text(s.split("\t: ")[1], color))
|
||||
.orElseGet(() -> Component.text("N/A", color));
|
||||
|
||||
InetAddress localHost = null;
|
||||
|
||||
try {
|
||||
localHost = InetAddress.getLocalHost();
|
||||
} catch (UnknownHostException ignored) {}
|
||||
} catch (final UnknownHostException ignored) { }
|
||||
|
||||
component = Component.translatable(
|
||||
"""
|
||||
Hostname: %s
|
||||
Working directory: %s
|
||||
OS architecture: %s
|
||||
OS version: %s
|
||||
OS name: %s
|
||||
CPU cores: %s
|
||||
CPU model: %s
|
||||
Threads: %s
|
||||
Heap memory usage: %s""",
|
||||
Component.text(localHost == null ? "N/A" : localHost.getHostName()).color(color),
|
||||
Component.text(System.getProperty("user.dir")).color(color),
|
||||
Component.text(os.getArch()).color(color),
|
||||
Component.text(os.getVersion()).color(color),
|
||||
Component.text(os.getName()).color(color),
|
||||
Component.text(String.valueOf(Runtime.getRuntime().availableProcessors())).color(color),
|
||||
"commands.info.server.output",
|
||||
bot.colorPalette.secondary,
|
||||
Component.text(localHost == null ? "N/A" : localHost.getHostName(), color),
|
||||
Component.text(System.getProperty("user.dir"), color),
|
||||
Component.text(os.getArch(), color),
|
||||
Component.text(os.getVersion(), color),
|
||||
Component.text(os.getName(), color),
|
||||
Component.text(String.valueOf(Runtime.getRuntime().availableProcessors()), color),
|
||||
cpuModel,
|
||||
Component.text(String.valueOf(Thread.activeCount())).color(color),
|
||||
Component.text(String.valueOf(Thread.activeCount()), color),
|
||||
Component
|
||||
.translatable(
|
||||
"%s MB / %s MB",
|
||||
color,
|
||||
Component.text(heapUsage.getUsed() / 1024L / 1024L),
|
||||
Component.text(heapUsage.getMax() / 1024L / 1024L)
|
||||
).color(color)
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary));
|
||||
),
|
||||
Component
|
||||
.translatable(
|
||||
"%s MB / %s MB",
|
||||
color,
|
||||
Component.text((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / 1024L / 1024L),
|
||||
Component.text(Runtime.getRuntime().totalMemory() / 1024L / 1024L)
|
||||
)
|
||||
);
|
||||
|
||||
return component;
|
||||
}
|
||||
|
@ -155,34 +170,53 @@ public class InfoCommand extends Command {
|
|||
final String uuid = bot.profile.getIdAsString();
|
||||
|
||||
return Component.translatable(
|
||||
"The bot's username is: %s and the UUID is: %s",
|
||||
"commands.info.botuser.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component
|
||||
.text(username)
|
||||
.text(username, bot.colorPalette.username)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component
|
||||
.text("Click here to copy the username to your clipboard")
|
||||
.color(NamedTextColor.GREEN)
|
||||
Component.translatable(
|
||||
"commands.generic.click_to_copy_username",
|
||||
NamedTextColor.GREEN
|
||||
)
|
||||
)
|
||||
)
|
||||
.clickEvent(
|
||||
ClickEvent.copyToClipboard(username)
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.username)),
|
||||
.clickEvent(ClickEvent.copyToClipboard(username)),
|
||||
Component
|
||||
.text(uuid)
|
||||
.text(uuid, bot.colorPalette.uuid)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component
|
||||
.text("Click here to copy the UUID to your clipboard")
|
||||
.color(NamedTextColor.GREEN)
|
||||
Component.translatable(
|
||||
"commands.generic.click_to_copy_uuid",
|
||||
NamedTextColor.GREEN
|
||||
)
|
||||
)
|
||||
)
|
||||
.clickEvent(
|
||||
ClickEvent.copyToClipboard(uuid)
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.uuid))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
.clickEvent(ClickEvent.copyToClipboard(uuid))
|
||||
);
|
||||
}
|
||||
case "botlogintime" -> {
|
||||
final long loginTime = bot.loginTime;
|
||||
|
||||
final ZoneId zoneId = ZoneId.of("UTC");
|
||||
|
||||
final String formattedLoginTime = TimeUtilities.formatTime(
|
||||
loginTime,
|
||||
"MMMM d, yyyy, hh:mm:ss a Z",
|
||||
zoneId
|
||||
);
|
||||
|
||||
final DateFormat timeSinceFormatter = new SimpleDateFormat("HH 'hours' mm 'minutes' ss 'seconds'");
|
||||
timeSinceFormatter.setTimeZone(TimeZone.getTimeZone(zoneId)); // very important
|
||||
final String formattedTimeSince = timeSinceFormatter.format(new Date(System.currentTimeMillis() - loginTime));
|
||||
|
||||
return Component.translatable(
|
||||
"commands.info.botlogintime.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(formattedLoginTime, bot.colorPalette.string),
|
||||
Component.text(formattedTimeSince, bot.colorPalette.string)
|
||||
);
|
||||
}
|
||||
case "uptime" -> {
|
||||
final long uptime = ManagementFactory.getRuntimeMXBean().getUptime() / 1000;
|
||||
|
@ -193,40 +227,83 @@ public class InfoCommand extends Command {
|
|||
final long seconds = TimeUnit.SECONDS.toSeconds(uptime) - (TimeUnit.SECONDS.toMinutes(uptime) * 60);
|
||||
|
||||
return Component.translatable(
|
||||
"The bots uptime is: %s",
|
||||
"commands.info.uptime.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable(
|
||||
"%s days, %s hours, %s minutes, %s seconds",
|
||||
"%s %s, %s %s, %s %s, %s %s",
|
||||
NamedTextColor.GREEN,
|
||||
Component.text(days),
|
||||
Component.text(StringUtilities.addPlural(days, "day")),
|
||||
Component.text(hours),
|
||||
Component.text(StringUtilities.addPlural(hours, "hour")),
|
||||
Component.text(minutes),
|
||||
Component.text(seconds)
|
||||
).color(NamedTextColor.GREEN)
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
Component.text(StringUtilities.addPlural(minutes, "minute")),
|
||||
Component.text(seconds),
|
||||
Component.text(StringUtilities.addPlural(seconds, "second"))
|
||||
)
|
||||
);
|
||||
}
|
||||
default -> {
|
||||
return Component.empty()
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
|
||||
.append(Component.text("ChomeNS Bot").color(NamedTextColor.YELLOW))
|
||||
.append(Component.space())
|
||||
return Component
|
||||
.translatable(
|
||||
"commands.info.default.main_output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text("ChomeNS Bot", NamedTextColor.YELLOW),
|
||||
Component
|
||||
.text("Kaboom")
|
||||
.style(
|
||||
Style.style()
|
||||
.color(NamedTextColor.GRAY)
|
||||
.decorate(TextDecoration.BOLD)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component
|
||||
.translatable(
|
||||
"is an open-source utility bot and a moderation bot made for " +
|
||||
"the %s Minecraft server (and its clones) " +
|
||||
"but also works on vanilla Minecraft servers. " +
|
||||
"It was originally made for fun but " +
|
||||
"I got addicted and made it a full blown bot."
|
||||
"commands.info.default.original_repository",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component
|
||||
.text(ORIGINAL_REPOSITORY_URL)
|
||||
.color(bot.colorPalette.string)
|
||||
.clickEvent(
|
||||
ClickEvent.openUrl(ORIGINAL_REPOSITORY_URL)
|
||||
)
|
||||
)
|
||||
.arguments(Component.text("Kaboom").style(Style.style().color(NamedTextColor.GRAY).decorate(TextDecoration.BOLD)))
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(Component.text("Original repository: "))
|
||||
.append(
|
||||
Component
|
||||
.text(ORIGINAL_REPOSITORY_URL)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
||||
.clickEvent(
|
||||
ClickEvent.openUrl(ORIGINAL_REPOSITORY_URL)
|
||||
.translatable(
|
||||
"commands.info.default.compiled_at",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component
|
||||
.text(BUILD_INFO.getProperty("build.date", "unknown"))
|
||||
.color(bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
.append(
|
||||
Component
|
||||
.translatable(
|
||||
"commands.info.default.git_commit",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component
|
||||
.text(BUILD_INFO.getProperty("build.git.commit.hash", "unknown"))
|
||||
.color(bot.colorPalette.string),
|
||||
Component
|
||||
.text(BUILD_INFO.getProperty("build.git.commit.count", "unknown"))
|
||||
.color(bot.colorPalette.number)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component
|
||||
.translatable(
|
||||
"commands.info.default.build",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component
|
||||
.text(BUILD_INFO.getProperty("build.number", "unknown"))
|
||||
.color(bot.colorPalette.number)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,40 +5,47 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.data.exploitMethods.Kick;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
public class KickCommand extends Command {
|
||||
public KickCommand () {
|
||||
super(
|
||||
"kick",
|
||||
"Kicks a player",
|
||||
new String[] { "<player>" },
|
||||
new String[] {},
|
||||
TrustLevel.TRUSTED,
|
||||
false
|
||||
new String[] {},
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
|
||||
final String allMethods = String.join(" | ", Arrays.stream(Kick.values()).map(Enum::name).toList());
|
||||
|
||||
this.usages = new String[] { "<" + allMethods + "> <player>" };
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final Kick method = context.getEnum(true, Kick.class);
|
||||
|
||||
final PlayerEntry entry = bot.players.getEntry(context.getString(true, true));
|
||||
|
||||
if (entry == null) throw new CommandException(Component.text("Invalid player name"));
|
||||
if (entry == null) throw new CommandException(Component.translatable("commands.generic.error.invalid_player"));
|
||||
|
||||
final String name = entry.profile.getName();
|
||||
final UUID uuid = entry.profile.getId();
|
||||
|
||||
bot.exploits.kick(uuid);
|
||||
bot.exploits.kick(method, uuid);
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Kicking player "))
|
||||
.append(Component.text(name).color(ColorUtilities.getColorByString(bot.config.colorPalette.username)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.kick.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(name, bot.colorPalette.username),
|
||||
Component.text(method.toString(), bot.colorPalette.string)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
|
@ -20,16 +19,14 @@ public class ListCommand extends Command {
|
|||
public ListCommand () {
|
||||
super(
|
||||
"list",
|
||||
"Lists all players in the server (including vanished)",
|
||||
new String[] {},
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
new String[] { "players" },
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(0);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
@ -38,45 +35,114 @@ public class ListCommand extends Command {
|
|||
|
||||
final List<Component> playersComponent = new ArrayList<>();
|
||||
|
||||
for (PlayerEntry entry : list) {
|
||||
for (final PlayerEntry entry : list) {
|
||||
if (entry == null) continue;
|
||||
|
||||
// chayapak
|
||||
// b58cac19-066b-307b-97b1-d6e19ed08d7c
|
||||
//
|
||||
// Usernames: foo, bar, baz or No other usernames associated
|
||||
// Vanished: false
|
||||
// Latency: 32
|
||||
// Game Mode: CREATIVE
|
||||
// IP Address: 127.0.0.1
|
||||
//
|
||||
// Click to copy the username to your clipboard
|
||||
// Shift+Click to insert the UUID into your chat box
|
||||
final Component hoverEvent = Component
|
||||
.text(entry.profile.getName())
|
||||
.append(Component.newline())
|
||||
.append(Component.text(entry.profile.getIdAsString(), bot.colorPalette.uuid))
|
||||
.append(Component.newline())
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
entry.persistingData.usernames.isEmpty()
|
||||
? Component.translatable(
|
||||
"commands.list.no_other_usernames",
|
||||
NamedTextColor.GRAY
|
||||
)
|
||||
: Component.translatable(
|
||||
"commands.list.with_usernames",
|
||||
bot.colorPalette.secondary,
|
||||
Component
|
||||
.join(
|
||||
JoinConfiguration.commas(true),
|
||||
entry.persistingData.usernames
|
||||
.stream()
|
||||
.map(Component::text)
|
||||
.toList()
|
||||
)
|
||||
.color(bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.list.vanished",
|
||||
bot.colorPalette.secondary,
|
||||
Component.text(!entry.persistingData.listed, bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.list.latency",
|
||||
bot.colorPalette.secondary,
|
||||
Component
|
||||
.text(entry.latency, bot.colorPalette.string) // using number color palette will not blend in (GOLD)
|
||||
.append(Component.text("ms"))
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.list.game_mode",
|
||||
bot.colorPalette.secondary,
|
||||
Component.text(entry.gamemode.name(), bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.list.ip_address",
|
||||
bot.colorPalette.secondary,
|
||||
Component.text(
|
||||
entry.persistingData.ip == null
|
||||
? "N/A"
|
||||
: entry.persistingData.ip,
|
||||
bot.colorPalette.string
|
||||
)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(Component.newline())
|
||||
.append(Component.translatable("commands.generic.click_to_copy_username", NamedTextColor.GREEN))
|
||||
.append(Component.newline())
|
||||
.append(Component.translatable("commands.generic.shift_click_to_insert_uuid", NamedTextColor.GREEN));
|
||||
|
||||
playersComponent.add(
|
||||
Component.translatable(
|
||||
"%s › %s",
|
||||
entry.displayName == null ?
|
||||
Component.text(entry.profile.getName()).color(ColorUtilities.getColorByString(bot.config.colorPalette.username)) :
|
||||
entry.displayName
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component
|
||||
.text(entry.profile.getName())
|
||||
.append(Component.newline())
|
||||
.append(Component.text("Click here to copy the username to your clipboard").color(NamedTextColor.GREEN))
|
||||
)
|
||||
)
|
||||
.clickEvent(
|
||||
ClickEvent.copyToClipboard(entry.profile.getName())
|
||||
)
|
||||
.color(NamedTextColor.WHITE),
|
||||
Component
|
||||
.text(entry.profile.getIdAsString())
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component.text("Click here to copy the UUID to your clipboard").color(NamedTextColor.GREEN)
|
||||
)
|
||||
)
|
||||
.clickEvent(
|
||||
ClickEvent.copyToClipboard(entry.profile.getIdAsString())
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.uuid))
|
||||
).color(NamedTextColor.DARK_GRAY)
|
||||
Component
|
||||
.translatable(
|
||||
"%s",
|
||||
entry.displayName == null ?
|
||||
Component.text(entry.profile.getName()) :
|
||||
entry.displayName
|
||||
)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(hoverEvent)
|
||||
)
|
||||
.clickEvent(
|
||||
ClickEvent.copyToClipboard(entry.profile.getName())
|
||||
)
|
||||
.insertion(entry.profile.getIdAsString())
|
||||
);
|
||||
}
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Players ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(list.size()).color(NamedTextColor.GRAY))
|
||||
.append(Component.text(")").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.translatable("commands.list.players_text", NamedTextColor.GREEN))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(list.size(), NamedTextColor.GRAY))
|
||||
.append(Component.text(")", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.join(JoinConfiguration.newlines(), playersComponent)
|
||||
|
|
|
@ -1,30 +1,23 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.Mail;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.plugins.MailPlugin;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import me.chayapak1.chomens_bot.util.PersistentDataUtilities;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import me.chayapak1.chomens_bot.data.mail.Mail;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.plugins.DatabasePlugin;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import me.chayapak1.chomens_bot.util.TimeUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
@ -33,212 +26,164 @@ public class MailCommand extends Command {
|
|||
public MailCommand () {
|
||||
super(
|
||||
"mail",
|
||||
"Sends a mail",
|
||||
new String[] { "send <player> <message>", "sendselecteditem <player>", "read" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
if (Main.database == null)
|
||||
throw new CommandException(Component.translatable("commands.generic.error.database_disabled"));
|
||||
|
||||
Main.database.checkOverloaded();
|
||||
|
||||
final PlayerEntry sender = context.sender;
|
||||
|
||||
final Gson gson = new Gson();
|
||||
|
||||
// kinda messy ngl
|
||||
|
||||
final String action = context.getString(false, true, true);
|
||||
final String action = context.getAction();
|
||||
|
||||
switch (action) {
|
||||
case "send" -> {
|
||||
int senderMailsSentTotal = 0;
|
||||
for (JsonElement mailElement : MailPlugin.mails) {
|
||||
final Mail mail = gson.fromJson(mailElement, Mail.class);
|
||||
case "send" -> DatabasePlugin.EXECUTOR_SERVICE.execute(() -> {
|
||||
try {
|
||||
bot.mail.send(
|
||||
new Mail(
|
||||
sender.profile.getName(),
|
||||
context.getString(false, true),
|
||||
Instant.now().toEpochMilli(),
|
||||
bot.getServerString(),
|
||||
context.getString(true, true)
|
||||
)
|
||||
);
|
||||
|
||||
if (mail.sentBy == null) continue;
|
||||
|
||||
if (!mail.sentBy.equals(sender.profile.getName())) continue;
|
||||
senderMailsSentTotal++;
|
||||
context.sendOutput(Component.translatable("commands.mail.sent", bot.colorPalette.defaultColor));
|
||||
} catch (final CommandException e) {
|
||||
context.sendOutput(e.message.colorIfAbsent(NamedTextColor.RED));
|
||||
}
|
||||
|
||||
if (senderMailsSentTotal > 256) {
|
||||
throw new CommandException(Component.text("You are sending too many mails!"));
|
||||
}
|
||||
|
||||
bot.mail.send(
|
||||
new Mail(
|
||||
sender.profile.getName(),
|
||||
context.getString(false, true),
|
||||
Instant.now().toEpochMilli(),
|
||||
bot.host + ":" + bot.port,
|
||||
context.getString(true, true)
|
||||
)
|
||||
);
|
||||
|
||||
return Component.text("Mail sent!").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
}
|
||||
});
|
||||
case "sendselecteditem" -> {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
int senderMailsSentTotal = 0;
|
||||
for (JsonElement mailElement : MailPlugin.mails) {
|
||||
final Mail mail = gson.fromJson(mailElement, Mail.class);
|
||||
|
||||
if (!mail.sentTo.equals(sender.profile.getName())) continue;
|
||||
senderMailsSentTotal++;
|
||||
}
|
||||
|
||||
if (senderMailsSentTotal > 256) {
|
||||
throw new CommandException(Component.text("You are sending too many mails!"));
|
||||
}
|
||||
|
||||
final CompletableFuture<Component> future = bot.core.runTracked(
|
||||
"minecraft:data get entity " +
|
||||
UUIDUtilities.selector(sender.profile.getId()) +
|
||||
" SelectedItem.components.minecraft:custom_data.message"
|
||||
final CompletableFuture<String> future = bot.query.entity(
|
||||
context.sender.profile.getIdAsString(),
|
||||
"SelectedItem.components.minecraft:custom_data.message"
|
||||
);
|
||||
|
||||
if (future == null) {
|
||||
throw new CommandException(Component.text("There was an error while sending your mail"));
|
||||
}
|
||||
|
||||
future.thenApplyAsync(output -> {
|
||||
future.thenApply(output -> {
|
||||
try {
|
||||
final List<Component> children = output.children();
|
||||
|
||||
if (
|
||||
!children.isEmpty() &&
|
||||
children.get(0).children().isEmpty() &&
|
||||
((TranslatableComponent) children.get(0)).key()
|
||||
.equals("arguments.nbtpath.nothing_found")
|
||||
) {
|
||||
context.sendOutput(Component.text("Player has no `message` NBT tag in their selected item's minecraft:custom_data").color(NamedTextColor.RED));
|
||||
return output;
|
||||
if (output.isEmpty()) {
|
||||
throw new CommandException(Component.translatable("commands.mail.sendselecteditem.error.no_item_nbt"));
|
||||
}
|
||||
|
||||
final Component actualOutputComponent = ((TranslatableComponent) output).arguments().get(1).asComponent();
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> {
|
||||
try {
|
||||
bot.mail.send(
|
||||
new Mail(
|
||||
sender.profile.getName(),
|
||||
context.getString(true, true),
|
||||
Instant.now().toEpochMilli(),
|
||||
bot.getServerString(),
|
||||
output
|
||||
)
|
||||
);
|
||||
|
||||
final String value = ComponentUtilities.stringify(actualOutputComponent);
|
||||
|
||||
if (!value.startsWith("\"") && !value.endsWith("\"") && !value.startsWith("'") && !value.endsWith("'")) {
|
||||
context.sendOutput(Component.text("`message` NBT is not a string").color(NamedTextColor.RED));
|
||||
return output;
|
||||
}
|
||||
|
||||
bot.mail.send(
|
||||
new Mail(
|
||||
sender.profile.getName(),
|
||||
context.getString(true, true),
|
||||
Instant.now().toEpochMilli(),
|
||||
bot.host + ":" + bot.port,
|
||||
value.substring(1).substring(0, value.length() - 2)
|
||||
)
|
||||
);
|
||||
} catch (CommandException e) {
|
||||
context.sendOutput(e.message.color(NamedTextColor.RED));
|
||||
return output;
|
||||
context.sendOutput(Component.translatable("commands.mail.sent", bot.colorPalette.defaultColor));
|
||||
} catch (final CommandException e) {
|
||||
context.sendOutput(e.message.colorIfAbsent(NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
} catch (final CommandException e) {
|
||||
context.sendOutput(e.message.colorIfAbsent(NamedTextColor.RED));
|
||||
return null;
|
||||
}
|
||||
|
||||
context.sendOutput(
|
||||
Component.text("Mail sent!").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
|
||||
);
|
||||
|
||||
return output;
|
||||
});
|
||||
}
|
||||
case "read" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
// TODO: use less for loops?
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> {
|
||||
final List<Mail> mails = bot.mail.list();
|
||||
|
||||
int senderMailSize = 0;
|
||||
for (JsonElement mailElement : MailPlugin.mails) {
|
||||
final Mail mail = gson.fromJson(mailElement, Mail.class);
|
||||
int senderMailSize = 0;
|
||||
for (final Mail mail : mails) {
|
||||
if (!mail.sentTo().equals(sender.profile.getName())) continue;
|
||||
senderMailSize++;
|
||||
}
|
||||
|
||||
if (!mail.sentTo.equals(sender.profile.getName())) continue;
|
||||
senderMailSize++;
|
||||
}
|
||||
if (senderMailSize == 0) {
|
||||
context.sendOutput(Component.translatable("commands.mail.read.no_new_mails", NamedTextColor.RED));
|
||||
return;
|
||||
}
|
||||
|
||||
if (senderMailSize == 0) {
|
||||
throw new CommandException(Component.text("You have no new mails"));
|
||||
}
|
||||
final int tempFinalSenderMailSize = senderMailSize;
|
||||
final List<Component> mailsComponent = new ArrayList<>();
|
||||
|
||||
final List<Component> mailsComponent = new ArrayList<>();
|
||||
int count = 1;
|
||||
for (final Mail mail : mails) {
|
||||
if (!mail.sentTo().equals(sender.profile.getName())) continue;
|
||||
|
||||
int i = 1;
|
||||
for (JsonElement mailElement : MailPlugin.mails) {
|
||||
final Mail mail = gson.fromJson(mailElement, Mail.class);
|
||||
final String formattedTime = TimeUtilities.formatTime(
|
||||
mail.timeSent(),
|
||||
"MMMM d, yyyy, hh:mm:ss a Z",
|
||||
ZoneId.of("UTC")
|
||||
);
|
||||
|
||||
if (!mail.sentTo.equals(sender.profile.getName())) continue;
|
||||
mailsComponent.add(
|
||||
Component.translatable(
|
||||
"commands.mail.read.mail_contents",
|
||||
NamedTextColor.GREEN,
|
||||
Component.text(count, bot.colorPalette.number),
|
||||
Component.text("-", NamedTextColor.DARK_GRAY),
|
||||
|
||||
final Instant instant = Instant.ofEpochMilli(mail.timeSent);
|
||||
final ZoneId zoneId = ZoneId.systemDefault();
|
||||
final OffsetDateTime localDateTime = OffsetDateTime.ofInstant(instant, zoneId);
|
||||
Component.text(mail.sentBy(), bot.colorPalette.username),
|
||||
Component
|
||||
.translatable("commands.mail.read.hover_more_info", NamedTextColor.GREEN)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component.translatable(
|
||||
"commands.mail.read.hover_info",
|
||||
NamedTextColor.GREEN,
|
||||
Component.text(formattedTime, bot.colorPalette.string),
|
||||
Component.text(mail.server(), bot.colorPalette.string)
|
||||
)
|
||||
)
|
||||
),
|
||||
Component.text(mail.contents(), NamedTextColor.WHITE)
|
||||
)
|
||||
);
|
||||
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy, hh:mm:ss a Z");
|
||||
final String formattedTime = localDateTime.format(formatter);
|
||||
count++;
|
||||
}
|
||||
|
||||
mailsComponent.add(
|
||||
Component.translatable(
|
||||
"""
|
||||
%s %s Sent by: %s %s
|
||||
Contents:
|
||||
%s""",
|
||||
Component.text(i).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
|
||||
Component.text("-").color(NamedTextColor.DARK_GRAY),
|
||||
final Component component = Component.empty()
|
||||
.append(Component.translatable("commands.mail.read.mails_text", NamedTextColor.GREEN))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(tempFinalSenderMailSize, NamedTextColor.GRAY))
|
||||
.append(Component.text(")", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.newline())
|
||||
.append(Component.join(JoinConfiguration.newlines(), mailsComponent));
|
||||
|
||||
Component.text(mail.sentBy).color(ColorUtilities.getColorByString(bot.config.colorPalette.username)),
|
||||
Component
|
||||
.text("[Hover here for more info]")
|
||||
.color(NamedTextColor.GREEN)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component.translatable(
|
||||
"""
|
||||
Time sent: %s
|
||||
Server: %s""",
|
||||
Component.text(formattedTime).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
Component.text(mail.server).color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
||||
).color(NamedTextColor.GREEN)
|
||||
)
|
||||
),
|
||||
Component.text(mail.contents).color(NamedTextColor.WHITE)
|
||||
).color(NamedTextColor.GREEN)
|
||||
);
|
||||
final Component renderedComponent = I18nUtilities.render(component);
|
||||
|
||||
i++;
|
||||
}
|
||||
if (context.inGame) {
|
||||
bot.chat.tellraw(
|
||||
renderedComponent,
|
||||
context.sender.profile.getId()
|
||||
);
|
||||
} else {
|
||||
context.sendOutput(renderedComponent);
|
||||
}
|
||||
|
||||
final Component component = Component.empty()
|
||||
.append(Component.text("Mails ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(senderMailSize).color(NamedTextColor.GRAY))
|
||||
.append(Component.text(")").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.newline())
|
||||
.append(Component.join(JoinConfiguration.newlines(), mailsComponent));
|
||||
|
||||
if (context.inGame) {
|
||||
bot.chat.tellraw(
|
||||
component,
|
||||
context.sender.profile.getId()
|
||||
);
|
||||
} else {
|
||||
context.sendOutput(component);
|
||||
}
|
||||
|
||||
for (JsonElement mailElement : MailPlugin.mails.deepCopy()) {
|
||||
final Mail mail = gson.fromJson(mailElement, Mail.class);
|
||||
|
||||
if (mail.sentTo.equals(sender.profile.getName())) MailPlugin.mails.remove(mailElement);
|
||||
}
|
||||
|
||||
PersistentDataUtilities.put("mails", MailPlugin.mails);
|
||||
bot.mail.clear(sender.profile.getName());
|
||||
});
|
||||
}
|
||||
default -> context.sendOutput(Component.text("Invalid action").color(NamedTextColor.RED));
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -1,46 +1,56 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.command.contexts.ConsoleCommandContext;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.data.listener.Listener;
|
||||
import me.chayapak1.chomens_bot.plugins.MusicPlayerPlugin;
|
||||
import me.chayapak1.chomens_bot.song.Instrument;
|
||||
import me.chayapak1.chomens_bot.song.Loop;
|
||||
import me.chayapak1.chomens_bot.song.Note;
|
||||
import me.chayapak1.chomens_bot.song.Song;
|
||||
import me.chayapak1.chomens_bot.util.*;
|
||||
import me.chayapak1.chomens_bot.util.Ascii85;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import me.chayapak1.chomens_bot.util.PathUtilities;
|
||||
import me.chayapak1.chomens_bot.util.TimestampUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.TranslatableComponent;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
import org.cloudburstmc.math.vector.Vector3d;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.nio.file.*;
|
||||
import java.util.ArrayList;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Base64;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import static me.chayapak1.chomens_bot.util.StringUtilities.isNotNullAndNotBlank;
|
||||
|
||||
public class MusicCommand extends Command {
|
||||
private Path root;
|
||||
public class MusicCommand extends Command implements Listener {
|
||||
private static final Path ROOT = MusicPlayerPlugin.SONG_DIR;
|
||||
|
||||
private static final AtomicInteger commandsPerSecond = new AtomicInteger();
|
||||
|
||||
public MusicCommand () {
|
||||
super(
|
||||
"music",
|
||||
"Plays music",
|
||||
new String[] {
|
||||
"play <song|URL>",
|
||||
"playitem",
|
||||
"stop",
|
||||
"loop <current|all|off>",
|
||||
"list [directory]",
|
||||
|
@ -50,6 +60,7 @@ public class MusicCommand extends Command {
|
|||
"goto <timestamp>",
|
||||
"pitch <pitch>",
|
||||
"speed <speed>",
|
||||
"volume <volume modifier>",
|
||||
"amplify <amplification>",
|
||||
"noteinstrument <instrument>",
|
||||
"pause",
|
||||
|
@ -58,187 +69,164 @@ public class MusicCommand extends Command {
|
|||
},
|
||||
new String[] { "song" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[] { ChatPacketType.DISGUISED }
|
||||
);
|
||||
|
||||
Main.EXECUTOR.scheduleAtFixedRate(() -> commandsPerSecond.set(0), 0, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
if (context.bot.music.locked) throw new CommandException(Component.text("Managing music is currently locked"));
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
// denis check
|
||||
if (commandsPerSecond.get() > 3) return null;
|
||||
else commandsPerSecond.getAndIncrement();
|
||||
|
||||
final String action = context.getString(false, true, true);
|
||||
if (context.bot.music.locked && !(context instanceof ConsoleCommandContext))
|
||||
throw new CommandException(Component.translatable("commands.music.error.locked"));
|
||||
|
||||
final String action = context.getAction();
|
||||
|
||||
root = MusicPlayerPlugin.SONG_DIR;
|
||||
return switch (action) {
|
||||
case "play", "playurl", "playnbs", "playnbsurl" -> play(context);
|
||||
case "playfromitem", "playitem" -> playFromItem(context);
|
||||
case "playsongplayer" -> playSongPlayer(context);
|
||||
case "playfromitem", "playitem", "playsongplayer" -> playFromItem(context);
|
||||
case "stop" -> stop(context);
|
||||
case "loop" -> loop(context);
|
||||
case "list" -> list(context);
|
||||
case "skip" -> skip(context);
|
||||
case "nowplaying" -> nowplaying(context);
|
||||
case "nowplaying" -> nowPlaying(context);
|
||||
case "queue" -> queue(context);
|
||||
case "goto" -> goTo(context);
|
||||
case "pitch" -> pitch(context);
|
||||
case "speed" -> speed(context);
|
||||
case "volume" -> volume(context);
|
||||
case "amplify" -> amplify(context);
|
||||
case "noteinstrument" -> noteInstrument(context);
|
||||
case "pause", "resume" -> pause(context);
|
||||
case "info" -> info(context);
|
||||
case "testsong" -> testSong(context);
|
||||
default -> Component.text("Invalid action").color(NamedTextColor.RED);
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
};
|
||||
}
|
||||
|
||||
public Component play (CommandContext context) throws CommandException {
|
||||
public Component play (final CommandContext context) throws CommandException {
|
||||
final MusicPlayerPlugin player = context.bot.music;
|
||||
|
||||
if (player.loaderThread != null) throw new CommandException(Component.text("Already loading a song"));
|
||||
if (player.loaderThread != null) throw new CommandException(Component.translatable("commands.music.play.error.already_loading"));
|
||||
|
||||
final String stringPath = context.getString(true, true);
|
||||
|
||||
final Path path;
|
||||
|
||||
String _path;
|
||||
Path path;
|
||||
try {
|
||||
_path = context.getString(true, true);
|
||||
path = Path.of(ROOT.toString(), stringPath);
|
||||
|
||||
// if (_path.isBlank()) throw new CommandException(Component.text("No song specified"));
|
||||
|
||||
path = Path.of(root.toString(), _path);
|
||||
|
||||
if (path.toString().contains("http")) player.loadSong(new URI(_path).toURL(), context.sender);
|
||||
if (path.toString().contains("http")) player.loadSong(new URI(stringPath).toURL(), context);
|
||||
else {
|
||||
// among us protection!!!11
|
||||
if (!path.normalize().startsWith(root.toString())) throw new CommandException(Component.text("no"));
|
||||
if (!path.normalize().startsWith(ROOT.toString())) throw new CommandException(Component.text("no"));
|
||||
|
||||
// ignore my ohio code for autocomplete
|
||||
final String separator = FileSystems.getDefault().getSeparator();
|
||||
|
||||
if (_path.contains(separator) && !_path.isEmpty()) {
|
||||
final String[] pathSplitted = _path.split(separator);
|
||||
if (stringPath.contains(separator) && !stringPath.isEmpty()) {
|
||||
final String[] splitPath = stringPath.split(separator);
|
||||
|
||||
final List<String> pathSplittedClone = new ArrayList<>(Arrays.stream(pathSplitted.clone()).toList());
|
||||
pathSplittedClone.remove(pathSplittedClone.size() - 1);
|
||||
final List<String> splitPathClone = new ObjectArrayList<>(Arrays.stream(splitPath).toList());
|
||||
splitPathClone.removeLast();
|
||||
|
||||
final Path realPath = Path.of(root.toString(), String.join(separator, pathSplittedClone));
|
||||
final Path realPath = Path.of(ROOT.toString(), String.join(separator, splitPathClone));
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(realPath)) {
|
||||
final List<Path> songsPaths = new ArrayList<>();
|
||||
for (Path eachPath : stream) songsPaths.add(eachPath);
|
||||
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(realPath)) {
|
||||
final List<Path> songsPaths = new ObjectArrayList<>();
|
||||
for (final Path eachPath : stream) songsPaths.add(eachPath);
|
||||
|
||||
PathUtilities.sort(songsPaths);
|
||||
|
||||
final List<String> songs = new ArrayList<>();
|
||||
for (Path eachPath : songsPaths) songs.add(eachPath.getFileName().toString());
|
||||
final List<String> songs = new ObjectArrayList<>();
|
||||
for (final Path eachPath : songsPaths) songs.add(eachPath.getFileName().toString());
|
||||
|
||||
final String lowerCaseFile = pathSplitted[pathSplitted.length - 1].toLowerCase();
|
||||
final String lowerCaseFile = splitPath[splitPath.length - 1].toLowerCase();
|
||||
|
||||
final String[] matchedArray = songs.stream()
|
||||
.filter(song -> song.equalsIgnoreCase(lowerCaseFile) || song.toLowerCase().contains(lowerCaseFile))
|
||||
.toArray(String[]::new);
|
||||
|
||||
if (matchedArray.length == 0) throw new CommandException(Component.text("Song not found"));
|
||||
if (matchedArray.length == 0) throw new CommandException(Component.translatable("commands.music.error.song_not_found"));
|
||||
|
||||
final String file = matchedArray[0];
|
||||
|
||||
player.loadSong(Path.of(realPath.toString(), file), context.sender);
|
||||
} catch (CommandException e) {
|
||||
throw e;
|
||||
} catch (NoSuchFileException e) {
|
||||
throw new CommandException(Component.text("Directory does not exist"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
player.loadSong(Path.of(realPath.toString(), file), context);
|
||||
} catch (final NoSuchFileException e) {
|
||||
throw new CommandException(Component.translatable("commands.music.error.no_directory"));
|
||||
}
|
||||
} else {
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(root)) {
|
||||
final List<Path> songsPaths = new ArrayList<>();
|
||||
for (Path eachPath : stream) songsPaths.add(eachPath);
|
||||
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(ROOT)) {
|
||||
final List<Path> songsPaths = new ObjectArrayList<>();
|
||||
for (final Path eachPath : stream) songsPaths.add(eachPath);
|
||||
|
||||
PathUtilities.sort(songsPaths);
|
||||
|
||||
final List<String> songs = new ArrayList<>();
|
||||
for (Path eachPath : songsPaths) songs.add(eachPath.getFileName().toString());
|
||||
final List<String> songs = new ObjectArrayList<>();
|
||||
for (final Path eachPath : songsPaths) songs.add(eachPath.getFileName().toString());
|
||||
|
||||
final String[] matchedArray = songs.stream()
|
||||
.filter(song -> song.equalsIgnoreCase(_path) || song.toLowerCase().contains(_path.toLowerCase()))
|
||||
.filter(song -> song.equalsIgnoreCase(stringPath) || song.toLowerCase().contains(stringPath.toLowerCase()))
|
||||
.toArray(String[]::new);
|
||||
|
||||
if (matchedArray.length == 0) throw new CommandException(Component.text("Song not found"));
|
||||
if (matchedArray.length == 0) throw new CommandException(Component.translatable("commands.music.error.song_not_found"));
|
||||
|
||||
final String file = matchedArray[0];
|
||||
|
||||
player.loadSong(Path.of(root.toString(), file), context.sender);
|
||||
} catch (CommandException e) {
|
||||
throw e;
|
||||
} catch (NoSuchFileException e) {
|
||||
player.loadSong(Path.of(ROOT.toString(), file), context);
|
||||
} catch (final NoSuchFileException e) {
|
||||
throw new CommandException(Component.text("this will never happen ok??"));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
throw new CommandException(Component.text("Invalid URL"));
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
throw new CommandException(Component.text("Song not found"));
|
||||
} catch (CommandException e) {
|
||||
} catch (final MalformedURLException e) {
|
||||
throw new CommandException(Component.translatable("commands.music.error.invalid_url"));
|
||||
} catch (final IndexOutOfBoundsException e) {
|
||||
throw new CommandException(Component.translatable("commands.music.error.song_not_found"));
|
||||
} catch (final CommandException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
} catch (final Exception e) {
|
||||
throw new CommandException(Component.text(e.toString()));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Component playFromItem (CommandContext context) throws CommandException {
|
||||
public Component playFromItem (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
// mail command lol
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final CompletableFuture<Component> future = bot.core.runTracked(
|
||||
"minecraft:data get entity " +
|
||||
UUIDUtilities.selector(context.sender.profile.getId()) +
|
||||
" SelectedItem.tag.SongItemData.SongData"
|
||||
final CompletableFuture<String> future = bot.query.entity(
|
||||
context.sender.profile.getIdAsString(),
|
||||
"SelectedItem.components.minecraft:custom_data.SongItemData.SongData"
|
||||
);
|
||||
|
||||
if (future == null) {
|
||||
throw new CommandException(Component.text("There was an error while getting your data"));
|
||||
}
|
||||
|
||||
future.thenApplyAsync(output -> {
|
||||
final List<Component> children = output.children();
|
||||
|
||||
if (
|
||||
!children.isEmpty() &&
|
||||
children.get(0).children().isEmpty() &&
|
||||
((TranslatableComponent) children.get(0)).key()
|
||||
.equals("arguments.nbtpath.nothing_found")
|
||||
) {
|
||||
context.sendOutput(Component.text("Player has no `SongItemData.SongData` NBT tag in their selected item").color(NamedTextColor.RED));
|
||||
return output;
|
||||
}
|
||||
|
||||
final Component actualOutputComponent = ((TranslatableComponent) output).arguments().get(1).asComponent();
|
||||
|
||||
final String value = ComponentUtilities.stringify(actualOutputComponent);
|
||||
|
||||
if (!value.startsWith("\"") && !value.endsWith("\"") && !value.startsWith("'") && !value.endsWith("'")) {
|
||||
context.sendOutput(Component.text("`data` NBT is not a string").color(NamedTextColor.RED));
|
||||
return output;
|
||||
future.thenApply(output -> {
|
||||
if (output.isEmpty()) {
|
||||
context.sendOutput(Component.translatable("commands.music.playitem.error.no_item_nbt", NamedTextColor.RED));
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
bot.music.loadSong(
|
||||
Base64.getDecoder().decode(
|
||||
value
|
||||
.substring(1)
|
||||
.substring(0, value.length() - 2)
|
||||
),
|
||||
context.sender
|
||||
Base64.getDecoder().decode(output),
|
||||
context
|
||||
);
|
||||
} catch (IllegalArgumentException e) {
|
||||
context.sendOutput(Component.text("Invalid base64 in the selected item").color(NamedTextColor.RED));
|
||||
} catch (final IllegalArgumentException e) {
|
||||
try {
|
||||
bot.music.loadSong(
|
||||
Ascii85.decode(output),
|
||||
context
|
||||
);
|
||||
} catch (final IllegalArgumentException e2) {
|
||||
context.sendOutput(Component.translatable("commands.music.playitem.invalid_data", NamedTextColor.RED));
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
|
@ -247,103 +235,57 @@ public class MusicCommand extends Command {
|
|||
return null;
|
||||
}
|
||||
|
||||
public Component playSongPlayer (CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
// dupe codes ??
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final CompletableFuture<Component> future = bot.core.runTracked(
|
||||
"minecraft:data get entity " +
|
||||
UUIDUtilities.selector(context.sender.profile.getId()) +
|
||||
" SelectedItem.components.minecraft:custom_data.SongItemData.SongData"
|
||||
);
|
||||
|
||||
if (future == null) {
|
||||
throw new CommandException(Component.text("There was an error while getting your data"));
|
||||
}
|
||||
|
||||
future.thenApplyAsync(output -> {
|
||||
final List<Component> children = output.children();
|
||||
|
||||
if (
|
||||
!children.isEmpty() &&
|
||||
!children.get(0).children().isEmpty() &&
|
||||
((TranslatableComponent) children.get(0).children().get(0))
|
||||
.key()
|
||||
.equals("arguments.nbtpath.nothing_found")
|
||||
) {
|
||||
context.sendOutput(Component.text("Player has no SongItemData -> SongData NBT tag in their selected item's minecraft:custom_data").color(NamedTextColor.RED));
|
||||
return output;
|
||||
}
|
||||
|
||||
final String value = ComponentUtilities.stringify(((TranslatableComponent) children.get(0)).arguments().get(1).asComponent());
|
||||
|
||||
if (!value.startsWith("\"") && !value.endsWith("\"") && !value.startsWith("'") && !value.endsWith("'")) {
|
||||
context.sendOutput(Component.text("NBT is not a string").color(NamedTextColor.RED));
|
||||
return output;
|
||||
}
|
||||
|
||||
try {
|
||||
bot.music.loadSong(
|
||||
Base64.getDecoder().decode(
|
||||
value
|
||||
.substring(1)
|
||||
.substring(0, value.length() - 2)
|
||||
),
|
||||
context.sender
|
||||
);
|
||||
} catch (IllegalArgumentException e) {
|
||||
context.sendOutput(Component.text("Invalid song data in the selected item").color(NamedTextColor.RED));
|
||||
}
|
||||
|
||||
return output;
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Component stop (CommandContext context) throws CommandException {
|
||||
public Component stop (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
bot.music.stopPlaying();
|
||||
bot.music.songQueue.clear();
|
||||
bot.music.loaderThread = null;
|
||||
|
||||
return Component.text("Cleared the song queue").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.music.stop", bot.colorPalette.defaultColor);
|
||||
}
|
||||
|
||||
public Component loop (CommandContext context) throws CommandException {
|
||||
public Component loop (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final Loop loop = context.getEnum(Loop.class);
|
||||
final Loop loop = context.getEnum(true, Loop.class);
|
||||
|
||||
bot.music.loop = loop;
|
||||
|
||||
switch (loop) {
|
||||
case OFF -> {
|
||||
return Component.empty()
|
||||
.append(Component.text("Looping is now "))
|
||||
.append(Component.text("disabled").color(NamedTextColor.RED))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.music.loop.off",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable("commands.music.loop.off.disabled", NamedTextColor.RED)
|
||||
);
|
||||
}
|
||||
case CURRENT -> {
|
||||
return Component.empty()
|
||||
.append(Component.text("Now looping "))
|
||||
.append(Component.text(bot.music.currentSong.name).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
if (bot.music.currentSong != null) {
|
||||
return Component.translatable(
|
||||
"commands.music.loop.current.with_song",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(bot.music.currentSong.name, bot.colorPalette.secondary)
|
||||
);
|
||||
} else {
|
||||
return Component.translatable(
|
||||
"commands.music.loop.current.without_song",
|
||||
bot.colorPalette.defaultColor
|
||||
);
|
||||
}
|
||||
}
|
||||
case ALL -> {
|
||||
return Component.text("Now looping every song").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.music.loop.all", bot.colorPalette.defaultColor);
|
||||
}
|
||||
default -> throw new CommandException(Component.text("Invalid action"));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Component list (CommandContext context) throws CommandException {
|
||||
public Component list (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String prefix = context.prefix;
|
||||
|
@ -351,31 +293,31 @@ public class MusicCommand extends Command {
|
|||
final String stringPathIfExists = context.getString(true, false);
|
||||
|
||||
final Path path = Path.of(
|
||||
root.toString(),
|
||||
ROOT.toString(),
|
||||
stringPathIfExists
|
||||
);
|
||||
|
||||
if (!path.normalize().startsWith(root.toString())) throw new CommandException(Component.text("no"));
|
||||
if (!path.normalize().startsWith(ROOT.toString())) throw new CommandException(Component.text("no"));
|
||||
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
|
||||
final List<Path> paths = new ArrayList<>();
|
||||
for (Path eachPath : stream) paths.add(eachPath);
|
||||
try (final DirectoryStream<Path> stream = Files.newDirectoryStream(path)) {
|
||||
final List<Path> paths = new ObjectArrayList<>();
|
||||
for (final Path eachPath : stream) paths.add(eachPath);
|
||||
|
||||
PathUtilities.sort(paths);
|
||||
|
||||
final List<Component> fullList = new ArrayList<>();
|
||||
final List<Component> fullList = new ObjectArrayList<>();
|
||||
int i = 0;
|
||||
for (Path eachPath : paths) {
|
||||
for (final Path eachPath : paths) {
|
||||
final boolean isDirectory = Files.isDirectory(eachPath);
|
||||
|
||||
Path location;
|
||||
try {
|
||||
location = path;
|
||||
} catch (IllegalArgumentException e) {
|
||||
} catch (final IllegalArgumentException e) {
|
||||
location = Paths.get(""); // wtf mabe
|
||||
}
|
||||
|
||||
final String joinedPath = location.equals(root) ?
|
||||
final String joinedPath = location.equals(ROOT) ?
|
||||
eachPath.getFileName().toString() :
|
||||
Paths.get(
|
||||
location.getFileName().toString(),
|
||||
|
@ -384,7 +326,7 @@ public class MusicCommand extends Command {
|
|||
|
||||
fullList.add(
|
||||
Component
|
||||
.text(eachPath.getFileName().toString(), (i++ & 1) == 0 ? ColorUtilities.getColorByString(bot.config.colorPalette.primary) : ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
||||
.text(eachPath.getFileName().toString(), (i++ & 1) == 0 ? bot.colorPalette.primary : bot.colorPalette.secondary)
|
||||
.clickEvent(
|
||||
ClickEvent.suggestCommand(
|
||||
prefix +
|
||||
|
@ -402,7 +344,7 @@ public class MusicCommand extends Command {
|
|||
|
||||
while (index <= fullList.size()) {
|
||||
// we MUST make a new copy of the list else everything will fard..,.
|
||||
List<Component> list = new ArrayList<>(fullList).subList(index, Math.min(index + eachSize, fullList.size()));
|
||||
final List<Component> list = new ObjectArrayList<>(fullList).subList(index, Math.min(index + eachSize, fullList.size()));
|
||||
|
||||
final Component component = Component.join(JoinConfiguration.separator(Component.space()), list);
|
||||
context.sendOutput(component);
|
||||
|
@ -410,68 +352,73 @@ public class MusicCommand extends Command {
|
|||
index += eachSize;
|
||||
list.clear();
|
||||
}
|
||||
} catch (NoSuchFileException e) {
|
||||
throw new CommandException(Component.text("Directory doesn't exist"));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (final IOException e) {
|
||||
throw new CommandException(Component.translatable("commands.music.error.no_directory"));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Component skip (CommandContext context) throws CommandException {
|
||||
public Component skip (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
final MusicPlayerPlugin music = bot.music;
|
||||
if (music.currentSong == null) throw new CommandException(Component.text("No song is currently playing"));
|
||||
if (music.currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing"));
|
||||
|
||||
context.sendOutput(
|
||||
Component.empty()
|
||||
.append(Component.text("Skipping "))
|
||||
.append(Component.text(music.currentSong.name).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor))
|
||||
);
|
||||
final String name = music.currentSong.name;
|
||||
|
||||
music.skip();
|
||||
|
||||
return null;
|
||||
return Component.translatable(
|
||||
"commands.music.skip",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(name, bot.colorPalette.secondary)
|
||||
);
|
||||
}
|
||||
|
||||
public Component nowplaying (CommandContext context) throws CommandException {
|
||||
public Component nowPlaying (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
final Song song = bot.music.currentSong;
|
||||
if (song == null) throw new CommandException(Component.text("No song is currently playing"));
|
||||
if (song == null) throw new CommandException(Component.translatable("commands.music.error.not_playing"));
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Now playing "))
|
||||
.append(Component.text(song.name).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.music.nowplaying",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(song.name, bot.colorPalette.secondary)
|
||||
);
|
||||
}
|
||||
|
||||
public Component queue (CommandContext context) throws CommandException {
|
||||
public Component queue (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
final List<Song> queue = bot.music.songQueue;
|
||||
|
||||
final List<Component> queueWithNames = new ArrayList<>();
|
||||
final List<Component> queueWithNames = new ObjectArrayList<>();
|
||||
int i = 0;
|
||||
for (Song song : queue) {
|
||||
for (final Song song : queue) {
|
||||
queueWithNames.add(
|
||||
Component.text(song.name).color((i++ & 1) == 0 ? ColorUtilities.getColorByString(bot.config.colorPalette.primary) : ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
||||
Component.text(
|
||||
song.name,
|
||||
(i++ & 1) == 0
|
||||
? bot.colorPalette.primary
|
||||
: bot.colorPalette.secondary
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Queue: ").color(NamedTextColor.GREEN))
|
||||
.append(Component.join(JoinConfiguration.separator(Component.text(", ")), queueWithNames));
|
||||
return Component.translatable(
|
||||
"commands.music.queue",
|
||||
NamedTextColor.GREEN,
|
||||
Component.join(JoinConfiguration.commas(true), queueWithNames)
|
||||
);
|
||||
}
|
||||
|
||||
// lazy fix for java using "goto" as keyword real
|
||||
public Component goTo (CommandContext context) throws CommandException {
|
||||
public Component goTo (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
final Song currentSong = bot.music.currentSong;
|
||||
|
||||
|
@ -479,132 +426,167 @@ public class MusicCommand extends Command {
|
|||
|
||||
final long timestamp = TimestampUtilities.parseTimestamp(input);
|
||||
|
||||
if (currentSong == null) throw new CommandException(Component.text("No song is currently playing"));
|
||||
if (currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing"));
|
||||
|
||||
if (timestamp < 0 || timestamp > currentSong.length) throw new CommandException(Component.text("Invalid timestamp"));
|
||||
if (timestamp < 0 || timestamp > currentSong.length / bot.music.speed)
|
||||
throw new CommandException(Component.translatable("commands.music.goto.error.invalid_timestamp"));
|
||||
|
||||
currentSong.setTime(timestamp);
|
||||
currentSong.setTime(timestamp / bot.music.speed);
|
||||
|
||||
return Component
|
||||
.text("Set the time to ")
|
||||
.append(Component.text(input).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.music.goto",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(input, bot.colorPalette.number)
|
||||
);
|
||||
}
|
||||
|
||||
public Component pitch (CommandContext context) throws CommandException {
|
||||
public Component pitch (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final float pitch = context.getFloat(true);
|
||||
final float pitch = context.getFloat(true, false);
|
||||
|
||||
bot.music.pitch = pitch;
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Set the pitch to "))
|
||||
.append(Component.text(pitch).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.music.pitch",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(pitch, bot.colorPalette.number)
|
||||
);
|
||||
}
|
||||
|
||||
public Component speed (CommandContext context) throws CommandException {
|
||||
public Component speed (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
final Song currentSong = bot.music.currentSong;
|
||||
|
||||
final float speed = context.getFloat(true);
|
||||
final double speed = context.getDouble(true, false);
|
||||
|
||||
if (speed > 5) throw new CommandException(Component.text("Too fast!"));
|
||||
if (speed > 5) throw new CommandException(Component.translatable("commands.music.speed.error.too_fast"));
|
||||
else if (speed < 0) throw new CommandException(Component.translatable("commands.music.speed.error.negative"));
|
||||
|
||||
long oldTime = -1;
|
||||
double oldTime = -1;
|
||||
|
||||
if (currentSong != null) oldTime = currentSong.time;
|
||||
if (currentSong != null) oldTime = currentSong.time / speed;
|
||||
|
||||
bot.music.speed = speed;
|
||||
|
||||
if (currentSong != null) currentSong.setTime(oldTime);
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Set the speed to "))
|
||||
.append(Component.text(speed).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.music.speed",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(speed, bot.colorPalette.number)
|
||||
);
|
||||
}
|
||||
|
||||
public Component amplify(CommandContext context) throws CommandException {
|
||||
public Component volume (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final float volume = context.getFloat(true, false);
|
||||
|
||||
bot.music.volume = volume;
|
||||
|
||||
return Component.translatable(
|
||||
"commands.music.volume",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(volume, bot.colorPalette.number)
|
||||
);
|
||||
}
|
||||
|
||||
public Component amplify (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(2);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final int amplify = context.getInteger(true);
|
||||
|
||||
if (amplify > 8) throw new CommandException(Component.text("Too big value"));
|
||||
if (amplify > 8) throw new CommandException(Component.translatable("commands.music.amplify.error.too_big_value"));
|
||||
else if (amplify < 0) throw new CommandException(Component.translatable("commands.music.amplify.error.negative"));
|
||||
|
||||
bot.music.amplify = amplify;
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Set the amplification to "))
|
||||
.append(Component.text(amplify).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.music.amplify",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(amplify, bot.colorPalette.number)
|
||||
);
|
||||
}
|
||||
|
||||
public Component noteInstrument (CommandContext context) throws CommandException {
|
||||
public Component noteInstrument (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String instrument = context.getString(true, true);
|
||||
|
||||
bot.music.instrument = instrument;
|
||||
|
||||
if (!instrument.equals("off")) {
|
||||
return Component.empty()
|
||||
.append(Component.text("Set the instrument for every note to "))
|
||||
.append(Component.text(instrument).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
if (instrument.equalsIgnoreCase("off")) {
|
||||
return Component.translatable("commands.music.noteinstrument.off", bot.colorPalette.defaultColor);
|
||||
} else {
|
||||
return Component.text("Every notes are now using its instrument").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.music.noteinstrument.set",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(instrument)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public Component pause (CommandContext context) throws CommandException {
|
||||
public Component pause (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
final Song currentSong = bot.music.currentSong;
|
||||
|
||||
if (currentSong == null) throw new CommandException(Component.text("No song is currently playing"));
|
||||
if (currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing"));
|
||||
|
||||
if (currentSong.paused) {
|
||||
currentSong.play();
|
||||
return Component.text("Resumed the current song").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.music.resumed", bot.colorPalette.defaultColor);
|
||||
} else {
|
||||
currentSong.pause();
|
||||
return Component.text("Paused the current song").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.music.paused", bot.colorPalette.defaultColor);
|
||||
}
|
||||
}
|
||||
|
||||
public Component info (CommandContext context) throws CommandException {
|
||||
public Component info (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
final Song currentSong = bot.music.currentSong;
|
||||
|
||||
if (currentSong == null) throw new CommandException(Component.text("No song is currently playing"));
|
||||
if (currentSong == null) throw new CommandException(Component.translatable("commands.music.error.not_playing"));
|
||||
|
||||
final List<Component> components = new ArrayList<>();
|
||||
final List<Component> components = new ObjectArrayList<>();
|
||||
|
||||
final TextColor keyColor = ColorUtilities.getColorByString(bot.config.colorPalette.secondary);
|
||||
final TextColor valueColor = ColorUtilities.getColorByString(bot.config.colorPalette.string);
|
||||
final TextColor keyColor = bot.colorPalette.secondary;
|
||||
final TextColor valueColor = bot.colorPalette.string;
|
||||
|
||||
if (isNotNullAndNotBlank(currentSong.name)) components.add(Component.translatable("Title/Filename: %s", Component.text(currentSong.name).color(valueColor)).color(keyColor));
|
||||
if (isNotNullAndNotBlank(currentSong.requester)) components.add(Component.translatable("Requester: %s", Component.text(currentSong.requester).color(valueColor)).color(keyColor));
|
||||
if (isNotNullAndNotBlank(currentSong.songAuthor)) components.add(Component.translatable("Author: %s", Component.text(currentSong.songAuthor).color(valueColor)).color(keyColor));
|
||||
if (isNotNullAndNotBlank(currentSong.songOriginalAuthor)) components.add(Component.translatable("Original author: %s", Component.text(currentSong.songOriginalAuthor).color(valueColor)).color(keyColor));
|
||||
if (isNotNullAndNotBlank(currentSong.tracks)) components.add(Component.translatable("Tracks: %s", Component.text(currentSong.tracks).color(valueColor)).color(keyColor));
|
||||
if (isNotNullAndNotBlank(currentSong.songDescription)) components.add(Component.translatable("Description: %s", Component.text(currentSong.songDescription).color(valueColor)).color(keyColor));
|
||||
final DecimalFormat formatter = new DecimalFormat("#,###");
|
||||
|
||||
final String formattedNotesCount = formatter.format(currentSong.size());
|
||||
|
||||
if (isNotNullAndNotBlank(currentSong.name))
|
||||
components.add(Component.translatable("commands.music.info.title", keyColor, Component.text(currentSong.name, valueColor)));
|
||||
if (currentSong.context != null && isNotNullAndNotBlank(currentSong.context.sender.profile.getName()))
|
||||
components.add(Component.translatable("commands.music.info.requester", keyColor, Component.text(currentSong.context.sender.profile.getName(), valueColor)));
|
||||
if (isNotNullAndNotBlank(currentSong.songAuthor))
|
||||
components.add(Component.translatable("commands.music.info.author", keyColor, Component.text(currentSong.songAuthor, valueColor)));
|
||||
if (isNotNullAndNotBlank(currentSong.songOriginalAuthor))
|
||||
components.add(Component.translatable("commands.music.info.original_author", keyColor, Component.text(currentSong.songOriginalAuthor, valueColor)));
|
||||
if (isNotNullAndNotBlank(currentSong.tracks))
|
||||
components.add(Component.translatable("commands.music.info.tracks", keyColor, Component.text(currentSong.tracks, valueColor)));
|
||||
components.add(Component.translatable("commands.music.info.notes", keyColor, Component.text(formattedNotesCount, valueColor)));
|
||||
if (isNotNullAndNotBlank(currentSong.songDescription))
|
||||
components.add(Component.translatable("commands.music.info.description", keyColor, Component.text(currentSong.songDescription, valueColor)));
|
||||
|
||||
return Component.join(JoinConfiguration.newlines(), components);
|
||||
}
|
||||
|
||||
public Component testSong (CommandContext context) throws CommandException {
|
||||
public Component testSong (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
@ -612,14 +594,16 @@ public class MusicCommand extends Command {
|
|||
final Song song = new Song(
|
||||
"test_song",
|
||||
bot,
|
||||
"Test Song",
|
||||
I18nUtilities.get("commands.music.testsong.title"),
|
||||
"chayapak",
|
||||
"hhhzzzsss",
|
||||
"SongPlayer's test song ported to ChomeNS Bot",
|
||||
I18nUtilities.get("commands.music.testsong.description"),
|
||||
null,
|
||||
false
|
||||
);
|
||||
|
||||
song.context = context;
|
||||
|
||||
int instrumentId = 0;
|
||||
int j = 0;
|
||||
for (int i = 0; i < 400; i++) {
|
||||
|
@ -632,8 +616,8 @@ public class MusicCommand extends Command {
|
|||
j,
|
||||
1,
|
||||
i * 50,
|
||||
-1,
|
||||
100
|
||||
Vector3d.ZERO,
|
||||
false
|
||||
)
|
||||
);
|
||||
|
||||
|
@ -648,6 +632,6 @@ public class MusicCommand extends Command {
|
|||
|
||||
bot.music.songQueue.add(song);
|
||||
|
||||
return Component.text("Test song has been added to the song queue").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.music.testsong.output", bot.colorPalette.defaultColor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,68 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.command.contexts.RemoteCommandContext;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NetCommandCommand extends Command {
|
||||
public NetCommandCommand () {
|
||||
super(
|
||||
"netcmd",
|
||||
new String[] { "<servers separated by a comma> <command>" },
|
||||
new String[] { "networkcommand", "irccommand", "remotecommand" },
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final String rawServers = context.getString(false, true, true);
|
||||
|
||||
final List<Bot> allBots = context.bot.bots;
|
||||
|
||||
final List<Bot> bots;
|
||||
|
||||
if (rawServers.equals("all")) {
|
||||
bots = allBots;
|
||||
} else {
|
||||
bots = new ArrayList<>();
|
||||
|
||||
final String[] servers = rawServers.split(",");
|
||||
|
||||
for (final Bot bot : allBots) {
|
||||
for (final String server : servers) {
|
||||
if (
|
||||
server.isBlank()
|
||||
|| !bot.getServerString(true)
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
.contains(server.toLowerCase())
|
||||
) continue;
|
||||
|
||||
bots.add(bot);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bots.isEmpty()) throw new CommandException(Component.translatable("commands.netcmd.error.no_servers_found"));
|
||||
|
||||
final String command = context.getString(true, true);
|
||||
|
||||
for (final Bot bot : bots) {
|
||||
if (!bot.loggedIn) continue;
|
||||
|
||||
final CommandContext remoteContext = new RemoteCommandContext(bot, context);
|
||||
|
||||
context.bot.commandHandler.executeCommand(command, remoteContext);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,9 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.util.ChatMessageUtilities;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
import net.kyori.adventure.text.event.HoverEvent;
|
||||
|
@ -16,44 +19,67 @@ public class NetMessageCommand extends Command {
|
|||
public NetMessageCommand () {
|
||||
super(
|
||||
"netmsg",
|
||||
"Broadcasts a message to all of the servers that the bot is connected",
|
||||
new String[] { "<message>" },
|
||||
new String[] { "networkmessage", "irc" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[]{ ChatPacketType.SYSTEM, ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
final List<Bot> bots = bot.bots;
|
||||
|
||||
final String hostAndPort = bot.host + ":" + bot.port;
|
||||
final String originServerName = bot.getServerString();
|
||||
final String originServerAddress = bot.getServerString(false);
|
||||
|
||||
Component serverNameComponent = Component
|
||||
.text(originServerName)
|
||||
.color(NamedTextColor.GRAY);
|
||||
|
||||
if (!bot.options.hidden) serverNameComponent = serverNameComponent
|
||||
.clickEvent(ClickEvent.copyToClipboard(originServerAddress))
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component.empty()
|
||||
.append(Component.text(originServerAddress, NamedTextColor.GRAY))
|
||||
.append(Component.newline())
|
||||
.append(Component.translatable("commands.netmsg.hover.copy_server_to_clipboard", NamedTextColor.GREEN))
|
||||
)
|
||||
);
|
||||
|
||||
final String rawMessage = context.getString(true, true);
|
||||
|
||||
final Component stylizedMessage = ChatMessageUtilities.applyChatMessageStyling(rawMessage);
|
||||
|
||||
final Component component = Component.translatable(
|
||||
"[%s]%s%s%s› %s",
|
||||
Component
|
||||
.text(hostAndPort)
|
||||
NamedTextColor.DARK_GRAY,
|
||||
serverNameComponent,
|
||||
Component.space(),
|
||||
context.sender.displayName == null ?
|
||||
Component.text(context.sender.profile.getName(), NamedTextColor.GRAY) :
|
||||
context.sender.displayName.color(NamedTextColor.GRAY),
|
||||
Component.space(),
|
||||
Component.empty()
|
||||
.append(stylizedMessage)
|
||||
.color(NamedTextColor.GRAY)
|
||||
.clickEvent(ClickEvent.copyToClipboard(hostAndPort))
|
||||
.clickEvent(ClickEvent.copyToClipboard(rawMessage))
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component.empty()
|
||||
.append(Component.text(hostAndPort).color(NamedTextColor.GRAY))
|
||||
.append(Component.newline())
|
||||
.append(Component.text("Click here to copy the server host and port to your clipboard").color(NamedTextColor.GREEN))
|
||||
Component.translatable(
|
||||
"commands.generic.click_to_copy_message",
|
||||
NamedTextColor.GREEN
|
||||
)
|
||||
)
|
||||
),
|
||||
Component.text(" "),
|
||||
context.sender.displayName == null ? Component.text(context.sender.profile.getName()).color(NamedTextColor.GRAY) : context.sender.displayName.color(NamedTextColor.GRAY),
|
||||
Component.text(" "),
|
||||
Component.text(context.getString(true, true)).color(NamedTextColor.GRAY)
|
||||
).color(NamedTextColor.DARK_GRAY);
|
||||
)
|
||||
);
|
||||
|
||||
for (Bot eachBot : bots) {
|
||||
for (final Bot eachBot : bots) {
|
||||
if (!eachBot.loggedIn) continue;
|
||||
eachBot.chat.tellraw(component);
|
||||
eachBot.chat.tellraw(I18nUtilities.render(component));
|
||||
}
|
||||
|
||||
return null;
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class PCrashCommand extends Command {
|
||||
public PCrashCommand () {
|
||||
super(
|
||||
"pcrash",
|
||||
"Crashes a player using particle",
|
||||
new String[] { "<player>" },
|
||||
new String[] { "particlecrash" },
|
||||
TrustLevel.TRUSTED,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final PlayerEntry player = bot.players.getEntry(context.getString(true, true));
|
||||
|
||||
if (player == null) throw new CommandException(Component.text("Invalid player name"));
|
||||
|
||||
bot.exploits.pcrash(player.profile.getId());
|
||||
|
||||
return Component.translatable(
|
||||
"Attempting to crash %s",
|
||||
Component.text(player.profile.getName()).color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
}
|
||||
}
|
|
@ -5,44 +5,79 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.command.contexts.PlayerCommandContext;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.MathUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
|
||||
public class RandomTeleportCommand extends Command {
|
||||
public RandomTeleportCommand () {
|
||||
super(
|
||||
"rtp",
|
||||
"Randomly teleports you",
|
||||
new String[] {},
|
||||
new String[] { "randomteleport" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[] { ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(0);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final PlayerEntry sender = context.sender;
|
||||
|
||||
final int positionX = MathUtilities.between(-1_000_000, 1_000_000);
|
||||
final int positionZ = MathUtilities.between(-1_000_000, 1_000_000);
|
||||
final String stringPosition = positionX + " 100 " + positionZ; // is hardcoding the y to 100 a great idea?
|
||||
final String position = String.format(
|
||||
"%d %d %d",
|
||||
MathUtilities.between(-1_000_000, 1_000_000),
|
||||
100,
|
||||
MathUtilities.between(-1_000_000, 1_000_000)
|
||||
);
|
||||
|
||||
bot.core.run("essentials:teleport " + sender.profile.getIdAsString() + " " + stringPosition);
|
||||
bot.core.run(
|
||||
String.format(
|
||||
"essentials:teleport %s %s",
|
||||
sender.profile.getIdAsString(),
|
||||
position
|
||||
)
|
||||
);
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Teleporting "))
|
||||
.append(Component.text(sender.profile.getName()).color(ColorUtilities.getColorByString(bot.config.colorPalette.username)))
|
||||
.append(Component.text(" to "))
|
||||
.append(Component.text(stringPosition).color(NamedTextColor.GREEN))
|
||||
.append(Component.text("..."))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
if (context instanceof final PlayerCommandContext playerContext) {
|
||||
playerContext.sendOutput(
|
||||
Component.translatable(
|
||||
"commands.rtp.teleporting_no_location",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(sender.profile.getName(), bot.colorPalette.username)
|
||||
)
|
||||
);
|
||||
|
||||
playerContext.sendOutput(
|
||||
Component.translatable(
|
||||
"commands.rtp.to_sender",
|
||||
Style.style()
|
||||
.color(NamedTextColor.GRAY)
|
||||
.decorate(TextDecoration.ITALIC)
|
||||
.build(),
|
||||
Component.text(position, NamedTextColor.GREEN)
|
||||
),
|
||||
true
|
||||
);
|
||||
|
||||
return null;
|
||||
} else {
|
||||
return Component.translatable(
|
||||
"commands.rtp.teleporting_location",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(sender.profile.getName(), bot.colorPalette.username),
|
||||
Component.text(position, NamedTextColor.GREEN)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,16 +11,14 @@ public class RefillCoreCommand extends Command {
|
|||
public RefillCoreCommand () {
|
||||
super(
|
||||
"refillcore",
|
||||
"Refills and resets the bots command core",
|
||||
new String[] {},
|
||||
new String[] { "rc" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(0);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
@ -28,6 +26,9 @@ public class RefillCoreCommand extends Command {
|
|||
bot.core.reset();
|
||||
bot.core.refill();
|
||||
|
||||
return null;
|
||||
return Component.translatable(
|
||||
"commands.refillcore.output",
|
||||
bot.colorPalette.defaultColor
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.I18nUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class RestartCommand extends Command {
|
||||
public RestartCommand () {
|
||||
super(
|
||||
"restart",
|
||||
new String[] { "[reason]" },
|
||||
new String[] {},
|
||||
TrustLevel.OWNER
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String reason = context.getString(true, false);
|
||||
|
||||
Main.stop(12, reason.isEmpty() ? null : reason, I18nUtilities.get("info.restarting"));
|
||||
|
||||
return Component.translatable("commands.restart.output", bot.colorPalette.defaultColor);
|
||||
}
|
||||
}
|
|
@ -5,29 +5,27 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.cloudburstmc.math.vector.Vector3i;
|
||||
|
||||
// this command uses english
|
||||
public class ScreenshareCommand extends Command {
|
||||
public ScreenshareCommand () {
|
||||
super(
|
||||
"screenshare",
|
||||
"Shares my screen",
|
||||
new String[] {
|
||||
"<start> <x> <y> <z>",
|
||||
"<stop>",
|
||||
"<setres> <width> <height>",
|
||||
"<setfps> <fps>"
|
||||
"start <x> <y> <z>",
|
||||
"stop",
|
||||
"setres <width> <height>",
|
||||
"setfps <fps>"
|
||||
},
|
||||
new String[] {},
|
||||
TrustLevel.TRUSTED,
|
||||
false
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String action = context.getString(false, true, true);
|
||||
|
@ -45,7 +43,7 @@ public class ScreenshareCommand extends Command {
|
|||
|
||||
return Component
|
||||
.text("Started screen sharing")
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
.color(bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "stop" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
@ -54,7 +52,7 @@ public class ScreenshareCommand extends Command {
|
|||
|
||||
return Component
|
||||
.text("Stopped screen sharing")
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
.color(bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "setres" -> {
|
||||
context.checkOverloadArgs(3);
|
||||
|
@ -69,8 +67,8 @@ public class ScreenshareCommand extends Command {
|
|||
|
||||
return Component
|
||||
.text("Set the resolution to ")
|
||||
.append(Component.text(width + "x" + height).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
.append(Component.text(width + "x" + height, bot.colorPalette.string))
|
||||
.color(bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "setfps" -> {
|
||||
context.checkOverloadArgs(2);
|
||||
|
@ -81,14 +79,12 @@ public class ScreenshareCommand extends Command {
|
|||
|
||||
return Component
|
||||
.text("Set the FPS to ")
|
||||
.append(Component.text(fps).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
}
|
||||
default -> {
|
||||
throw new CommandException(Component.text("Invalid action"));
|
||||
.append(Component.text(fps, bot.colorPalette.number))
|
||||
.color(bot.colorPalette.defaultColor);
|
||||
}
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
} catch (final NumberFormatException e) {
|
||||
throw new CommandException(Component.text("Invalid integer"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.plugins.PlayersPersistentDataPlugin;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.plugins.DatabasePlugin;
|
||||
import me.chayapak1.chomens_bot.util.TimeUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.ZoneId;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -22,66 +22,84 @@ public class SeenCommand extends Command {
|
|||
public SeenCommand () {
|
||||
super(
|
||||
"seen",
|
||||
"Shows the last seen of a player",
|
||||
new String[] { "<player>" },
|
||||
new String[] { "lastseen" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws Exception {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
if (Main.database == null)
|
||||
throw new CommandException(Component.translatable("commands.generic.error.database_disabled"));
|
||||
|
||||
Main.database.checkOverloaded();
|
||||
|
||||
final String player = context.getString(true, true);
|
||||
|
||||
boolean online = false;
|
||||
|
||||
final List<Component> onlineComponents = new ArrayList<>();
|
||||
|
||||
for (Bot eachBot : bot.bots) {
|
||||
for (final Bot eachBot : bot.bots) {
|
||||
if (eachBot.players.getEntry(player) != null) {
|
||||
online = true;
|
||||
|
||||
onlineComponents.add(
|
||||
Component.empty()
|
||||
.append(Component.text(player))
|
||||
.append(Component.text(" is currently online on "))
|
||||
.append(Component.text(eachBot.host + ":" + eachBot.port))
|
||||
.color(NamedTextColor.RED)
|
||||
Component.translatable(
|
||||
"commands.seen.error.currently_online",
|
||||
NamedTextColor.RED,
|
||||
Component.text(player),
|
||||
Component.text(eachBot.getServerString())
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (online) return Component.join(JoinConfiguration.newlines(), onlineComponents);
|
||||
|
||||
final JsonElement playerElement = PlayersPersistentDataPlugin.playersObject.get(player);
|
||||
if (playerElement == null) throw new CommandException(Component.translatable(
|
||||
"%s was never seen",
|
||||
Component.text(player)
|
||||
));
|
||||
DatabasePlugin.EXECUTOR_SERVICE.execute(() -> {
|
||||
try {
|
||||
final JsonNode playerElement = bot.playersDatabase.getPlayerData(player);
|
||||
if (playerElement == null) throw new CommandException(Component.translatable(
|
||||
"commands.seen.error.never_seen",
|
||||
Component.text(player)
|
||||
));
|
||||
|
||||
final JsonObject lastSeen = playerElement.getAsJsonObject().get("lastSeen").getAsJsonObject();
|
||||
final ObjectNode lastSeen = (ObjectNode) playerElement.get("lastSeen");
|
||||
|
||||
final JsonElement time = lastSeen.get("time");
|
||||
if (lastSeen == null || lastSeen.isNull())
|
||||
throw new CommandException(Component.translatable("commands.seen.error.no_last_seen_entry"));
|
||||
|
||||
if (time == null) throw new CommandException(Component.text("This player does not have the `lastSeen.time` entry in the database for some reason."));
|
||||
final JsonNode time = lastSeen.get("time");
|
||||
|
||||
final Instant instant = Instant.ofEpochMilli(time.getAsLong());
|
||||
final ZoneId zoneId = ZoneId.of("UTC"); // should i be doing this?
|
||||
final OffsetDateTime localDateTime = OffsetDateTime.ofInstant(instant, zoneId);
|
||||
if (time == null || time.isNull())
|
||||
throw new CommandException(Component.translatable("commands.seen.error.no_time_entry"));
|
||||
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy, hh:mm:ss a Z");
|
||||
final String formattedTime = localDateTime.format(formatter);
|
||||
final String formattedTime = TimeUtilities.formatTime(
|
||||
time.asLong(),
|
||||
"EEEE, MMMM d, yyyy, hh:mm:ss a Z",
|
||||
ZoneId.of("UTC")
|
||||
);
|
||||
|
||||
final String server = lastSeen.get("server").getAsString();
|
||||
final String server = lastSeen.get("server").asText();
|
||||
|
||||
return Component.translatable(
|
||||
"%s was last seen at %s on %s",
|
||||
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username)),
|
||||
Component.text(formattedTime).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
Component.text(server).color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
context.sendOutput(
|
||||
Component.translatable(
|
||||
"commands.seen.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(player, bot.colorPalette.username),
|
||||
Component.text(formattedTime, bot.colorPalette.string),
|
||||
Component.text(server, bot.colorPalette.string)
|
||||
)
|
||||
);
|
||||
} catch (final CommandException e) {
|
||||
context.sendOutput(e.message.color(NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,45 +7,116 @@ import me.chayapak1.chomens_bot.command.CommandException;
|
|||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import org.luaj.vm2.Globals;
|
||||
import org.luaj.vm2.LuaValue;
|
||||
import org.luaj.vm2.lib.jse.CoerceJavaToLua;
|
||||
import org.luaj.vm2.lib.jse.JsePlatform;
|
||||
import party.iroiro.luajava.Lua;
|
||||
import party.iroiro.luajava.lua54.Lua54;
|
||||
import party.iroiro.luajava.value.LuaValue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class ServerEvalCommand extends Command {
|
||||
public Lua lua;
|
||||
|
||||
public ServerEvalCommand () {
|
||||
super(
|
||||
"servereval",
|
||||
"Evaluate codes using LuaJ",
|
||||
new String[] { "<code>" },
|
||||
new String[] { "reset", "<code>" },
|
||||
new String[] {},
|
||||
TrustLevel.OWNER,
|
||||
false
|
||||
TrustLevel.OWNER
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
bot.executorService.submit(() -> {
|
||||
final String code = context.getString(true, true);
|
||||
|
||||
if (code.equalsIgnoreCase("reset")) {
|
||||
if (lua != null) lua.close();
|
||||
lua = null;
|
||||
|
||||
return Component.translatable("commands.servereval.reset", bot.colorPalette.defaultColor);
|
||||
}
|
||||
|
||||
bot.executorService.execute(() -> {
|
||||
try {
|
||||
final Globals globals = JsePlatform.standardGlobals();
|
||||
if (lua == null) lua = new Lua54();
|
||||
|
||||
globals.set("bot", CoerceJavaToLua.coerce(bot));
|
||||
globals.set("class", CoerceJavaToLua.coerce(Class.class));
|
||||
globals.set("context", CoerceJavaToLua.coerce(context));
|
||||
lua.openLibraries();
|
||||
|
||||
LuaValue chunk = globals.load(context.getString(true, true));
|
||||
lua.set("lua", lua);
|
||||
lua.set("bot", bot);
|
||||
lua.set("context", context);
|
||||
lua.set("shell", new Shell());
|
||||
|
||||
final LuaValue output = chunk.call();
|
||||
final LuaValue[] values = lua.eval(code);
|
||||
|
||||
context.sendOutput(Component.text(output.toString()).color(NamedTextColor.GREEN));
|
||||
} catch (Exception e) {
|
||||
context.sendOutput(Component.text(e.toString()).color(NamedTextColor.RED));
|
||||
final StringBuilder output = new StringBuilder();
|
||||
|
||||
if (values.length != 1) {
|
||||
output.append('[');
|
||||
|
||||
int i = 1;
|
||||
for (final LuaValue value : values) {
|
||||
output.append(getString(value));
|
||||
if (i++ != values.length) output.append(", ");
|
||||
}
|
||||
|
||||
output.append(']');
|
||||
} else {
|
||||
output.append(getString(values[0]));
|
||||
}
|
||||
|
||||
context.sendOutput(Component.text(output.toString(), NamedTextColor.GREEN));
|
||||
} catch (final Exception e) {
|
||||
context.sendOutput(Component.text(e.toString(), NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getString (final LuaValue luaValue) {
|
||||
final Object javaObject = luaValue.toJavaObject();
|
||||
|
||||
if (javaObject == null) return luaValue.toString();
|
||||
else return javaObject.toString();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") // we actually use it in lua itself :)
|
||||
public static final class Shell {
|
||||
public String execute (final String[] command) throws Exception {
|
||||
final ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
|
||||
processBuilder.command(command);
|
||||
|
||||
final Process process = processBuilder.start();
|
||||
|
||||
final StringBuilder output = new StringBuilder();
|
||||
|
||||
final BufferedReader stdoutReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
|
||||
|
||||
int character;
|
||||
|
||||
while ((character = stdoutReader.read()) != -1) {
|
||||
final char[] chars = Character.toChars(character);
|
||||
final String string = new String(chars);
|
||||
output.append(string);
|
||||
}
|
||||
|
||||
final BufferedReader stderrReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
|
||||
|
||||
while ((character = stderrReader.read()) != -1) {
|
||||
final char[] chars = Character.toChars(character);
|
||||
final String string = new String(chars);
|
||||
output.append("[STDERR] ").append(string);
|
||||
}
|
||||
|
||||
process.waitFor(10, TimeUnit.SECONDS);
|
||||
|
||||
return output.toString();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,29 +6,26 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class StopCommand extends Command {
|
||||
public StopCommand () {
|
||||
super(
|
||||
"stop",
|
||||
"Gracefully stops the bot",
|
||||
new String[] { "" },
|
||||
new String[] { "[reason]" },
|
||||
new String[] {},
|
||||
TrustLevel.OWNER,
|
||||
false
|
||||
TrustLevel.OWNER
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(0);
|
||||
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
Main.stop();
|
||||
final String reason = context.getString(true, false);
|
||||
|
||||
return Component.text("Stopping").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
Main.stop(0, reason.isEmpty() ? null : reason);
|
||||
|
||||
return Component.translatable("commands.stop.output", bot.colorPalette.defaultColor);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
|
@ -13,16 +12,14 @@ public class TPSBarCommand extends Command {
|
|||
public TPSBarCommand () {
|
||||
super(
|
||||
"tpsbar",
|
||||
"Shows the server's TPS using Minecraft Bossbar",
|
||||
new String[] { "<on|off>" },
|
||||
new String[] { "tps" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
@ -32,21 +29,21 @@ public class TPSBarCommand extends Command {
|
|||
switch (action) {
|
||||
case "on" -> {
|
||||
bot.tps.on();
|
||||
return Component.empty()
|
||||
.append(Component.text("TPSBar is now "))
|
||||
.append(Component.text("enabled").color(NamedTextColor.GREEN))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable(
|
||||
"commands.tpsbar.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable("commands.generic.enabled", NamedTextColor.GREEN)
|
||||
);
|
||||
}
|
||||
case "off" -> {
|
||||
bot.tps.off();
|
||||
return Component.empty()
|
||||
.append(Component.text("TPSBar is now "))
|
||||
.append(Component.text("disabled").color(NamedTextColor.RED))
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
}
|
||||
default -> {
|
||||
throw new CommandException(Component.text("Invalid action"));
|
||||
return Component.translatable(
|
||||
"commands.tpsbar.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.translatable("commands.generic.disabled", NamedTextColor.RED)
|
||||
);
|
||||
}
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,22 +11,21 @@ public class TestCommand extends Command {
|
|||
public TestCommand () {
|
||||
super(
|
||||
"test",
|
||||
"Tests if the bot is working",
|
||||
new String[] { "[args]" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
return Component.translatable(
|
||||
"Hello, World! Username: %s, Sender UUID: %s, Prefix: %s, Args: %s",
|
||||
"commands.test.output",
|
||||
NamedTextColor.GREEN,
|
||||
Component.text(context.sender.profile.getName()),
|
||||
Component.text(context.sender.profile.getIdAsString()),
|
||||
Component.text(context.prefix),
|
||||
Component.text(context.getString(true, false))
|
||||
).color(NamedTextColor.GREEN);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,47 +5,45 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.util.TimeUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.time.DateTimeException;
|
||||
import java.time.Instant;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class TimeCommand extends Command {
|
||||
public TimeCommand () {
|
||||
super(
|
||||
"time",
|
||||
"Shows the date and time for the specified timezone",
|
||||
new String[] { "<timezone>" },
|
||||
new String[] { "dateandtime", "date" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
try {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String timezone = context.getString(true, true);
|
||||
|
||||
final ZoneId zoneId = ZoneId.of(timezone);
|
||||
final ZonedDateTime zonedDateTime = ZonedDateTime.now(zoneId);
|
||||
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEEE, MMMM d, yyyy, hh:mm:ss a");
|
||||
final String formattedTime = zonedDateTime.format(formatter);
|
||||
final String formattedTime = TimeUtilities.formatTime(
|
||||
Instant.now().toEpochMilli(),
|
||||
"EEEE, MMMM d, yyyy, hh:mm:ss a",
|
||||
ZoneId.of(timezone)
|
||||
);
|
||||
|
||||
return Component.translatable(
|
||||
"The current time for %s is: %s",
|
||||
Component.text(timezone).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
Component.text(formattedTime).color(NamedTextColor.GREEN)
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
} catch (DateTimeException e) {
|
||||
throw new CommandException(Component.text("Invalid timezone (case-sensitive)"));
|
||||
"commands.time.output",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(timezone, bot.colorPalette.string),
|
||||
Component.text(formattedTime, NamedTextColor.GREEN)
|
||||
);
|
||||
} catch (final DateTimeException e) {
|
||||
throw new CommandException(Component.translatable("commands.time.error.invalid_timezone"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,36 +1,47 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.util.HttpUtilities;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
|
||||
// stolen from vencord :D
|
||||
// https://github.com/Vendicated/Vencord/blob/1fa6181f7e6526e1bf2e85260d9051000916c47c/src/plugins/translate/utils.ts
|
||||
public class TranslateCommand extends Command {
|
||||
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
|
||||
private static final String TRANSLATE_URL = "https://translate-pa.googleapis.com/v1/translate?" +
|
||||
"params.client=gtx&" +
|
||||
"dataTypes=TRANSLATION&" +
|
||||
"key=AIzaSyDLEeFI5OtFBwYBIoK_jj5m32rZK5CkCXA&" + // some google API key :eyes:
|
||||
"query.sourceLanguage=%s&" +
|
||||
"query.targetLanguage=%s&" +
|
||||
"query.text=%s";
|
||||
|
||||
public TranslateCommand () {
|
||||
super(
|
||||
"translate",
|
||||
"Translates a message using Google Translate",
|
||||
new String[] { "<fromLanguage> <toLanguage> <message>" },
|
||||
new String[] { "<from> <to> <message>" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[] { ChatPacketType.SYSTEM, ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String from = context.getString(false, true);
|
||||
|
@ -38,47 +49,58 @@ public class TranslateCommand extends Command {
|
|||
|
||||
final String message = context.getString(true, true);
|
||||
|
||||
final Gson gson = new Gson();
|
||||
|
||||
bot.executorService.submit(() -> {
|
||||
bot.executorService.execute(() -> {
|
||||
try {
|
||||
final URL url = new URL("https://translate.google.com/translate_a/single?client=at&dt=t&dt=rm&dj=1");
|
||||
|
||||
final String jsonOutput = HttpUtilities.postRequest(
|
||||
url,
|
||||
"application/x-www-form-urlencoded;charset=utf-8",
|
||||
final URL url = new URI(
|
||||
String.format(
|
||||
"sl=%s&tl=%s&q=%s",
|
||||
from,
|
||||
to,
|
||||
URLEncoder.encode(
|
||||
message,
|
||||
StandardCharsets.UTF_8
|
||||
)
|
||||
TRANSLATE_URL,
|
||||
URLEncoder.encode(from, StandardCharsets.UTF_8),
|
||||
URLEncoder.encode(to, StandardCharsets.UTF_8),
|
||||
URLEncoder.encode(message, StandardCharsets.UTF_8)
|
||||
)
|
||||
);
|
||||
).toURL();
|
||||
|
||||
final JsonObject jsonObject = gson.fromJson(jsonOutput, JsonObject.class);
|
||||
|
||||
final JsonArray sentences = jsonObject.getAsJsonArray("sentences");
|
||||
|
||||
final JsonObject translation = sentences.get(0).getAsJsonObject();
|
||||
|
||||
final String output = translation.get("trans").getAsString();
|
||||
final Result result = OBJECT_MAPPER.readValue(url, Result.class);
|
||||
|
||||
context.sendOutput(
|
||||
Component
|
||||
.translatable(
|
||||
"Result: %s",
|
||||
Component.text(output).color(NamedTextColor.GREEN)
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
||||
.translatable(
|
||||
"commands.translate.result",
|
||||
bot.colorPalette.secondary,
|
||||
Component.text(result.translation(), NamedTextColor.GREEN)
|
||||
)
|
||||
);
|
||||
} catch (Exception e) {
|
||||
context.sendOutput(Component.text(e.toString()).color(NamedTextColor.RED));
|
||||
} catch (final Exception e) {
|
||||
context.sendOutput(Component.text(e.toString(), NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/*
|
||||
$ curl "https://translate-pa.googleapis.com/v1/translate?params.client=gtx&dataTypes=TRANSLATION&key=AIzaSyDLEeFI5OtFBwYBIoK_jj5m32rZK5CkCXA&query.sourceLanguage=auto&query.targetLanguage=ja&query.text=hello"
|
||||
{
|
||||
"translation": "こんにちは",
|
||||
"detectedLanguages": {
|
||||
"srclangs": [
|
||||
"en"
|
||||
],
|
||||
"extendedSrclangs": [
|
||||
"en"
|
||||
]
|
||||
},
|
||||
"sourceLanguage": "en"
|
||||
}
|
||||
*/
|
||||
private record Result(
|
||||
@JsonValue String translation,
|
||||
@JsonValue String sourceLanguage,
|
||||
@JsonValue DetectedLanguages detectedLanguages
|
||||
) {
|
||||
private record DetectedLanguages(
|
||||
@JsonValue List<String> srclangs,
|
||||
@JsonValue List<String> extendedSrclangs
|
||||
) { }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,8 +5,7 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.util.UUIDUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
|
@ -17,16 +16,14 @@ public class UUIDCommand extends Command {
|
|||
public UUIDCommand () {
|
||||
super(
|
||||
"uuid",
|
||||
"Shows your UUID or other player's UUID",
|
||||
new String[] { "[username]" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String player = context.getString(true, false);
|
||||
|
@ -34,8 +31,8 @@ public class UUIDCommand extends Command {
|
|||
if (!player.isEmpty()) {
|
||||
final PlayerEntry entry = bot.players.getEntry(player);
|
||||
|
||||
String name;
|
||||
String uuid;
|
||||
final String name;
|
||||
final String uuid;
|
||||
|
||||
if (entry == null) {
|
||||
name = player;
|
||||
|
@ -46,39 +43,45 @@ public class UUIDCommand extends Command {
|
|||
}
|
||||
|
||||
return Component.translatable(
|
||||
"%s's UUID: %s",
|
||||
"commands.uuid.other",
|
||||
NamedTextColor.GREEN,
|
||||
Component.text(name),
|
||||
Component
|
||||
.text(uuid)
|
||||
.text(uuid, bot.colorPalette.uuid)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component.text("Click here to copy the UUID to your clipboard").color(NamedTextColor.GREEN)
|
||||
Component.translatable(
|
||||
"commands.generic.click_to_copy_uuid",
|
||||
NamedTextColor.GREEN
|
||||
)
|
||||
)
|
||||
)
|
||||
.clickEvent(
|
||||
ClickEvent.copyToClipboard(uuid)
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.uuid))
|
||||
).color(NamedTextColor.GREEN);
|
||||
);
|
||||
} else {
|
||||
final PlayerEntry entry = context.sender;
|
||||
|
||||
final String uuid = entry.profile.getIdAsString();
|
||||
|
||||
return Component.translatable(
|
||||
"Your UUID: %s",
|
||||
"commands.uuid.self",
|
||||
NamedTextColor.GREEN,
|
||||
Component
|
||||
.text(uuid)
|
||||
.text(uuid, bot.colorPalette.uuid)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
Component.text("Click here to copy the UUID to your clipboard").color(NamedTextColor.GREEN)
|
||||
Component.translatable(
|
||||
"commands.generic.click_to_copy_uuid",
|
||||
NamedTextColor.GREEN
|
||||
)
|
||||
)
|
||||
)
|
||||
.clickEvent(
|
||||
ClickEvent.copyToClipboard(uuid)
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.uuid))
|
||||
).color(NamedTextColor.GREEN);
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,9 +6,12 @@ import com.google.gson.JsonElement;
|
|||
import com.google.gson.JsonObject;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.Main;
|
||||
import me.chayapak1.chomens_bot.command.*;
|
||||
import me.chayapak1.chomens_bot.command.*;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.command.contexts.DiscordCommandContext;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.util.HttpUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.event.ClickEvent;
|
||||
|
@ -17,30 +20,32 @@ import net.kyori.adventure.text.format.NamedTextColor;
|
|||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DecimalFormat;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class UrbanCommand extends Command {
|
||||
public int requestsPerSecond = 0;
|
||||
public final AtomicInteger requestsPerSecond = new AtomicInteger();
|
||||
|
||||
public UrbanCommand () {
|
||||
super(
|
||||
"urban",
|
||||
"Urban Dictionary in Minecraft",
|
||||
new String[] { "<term>" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[]{ ChatPacketType.DISGUISED }
|
||||
);
|
||||
|
||||
Main.executor.scheduleAtFixedRate(() -> requestsPerSecond = 0, 0, 1, TimeUnit.SECONDS);
|
||||
Main.EXECUTOR.scheduleAtFixedRate(() -> requestsPerSecond.set(0), 0, 1, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public Component execute (CommandContext context) throws CommandException {
|
||||
if (requestsPerSecond > 3) throw new CommandException(Component.text("Too many requests"));
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
if (requestsPerSecond.get() > 3) throw new CommandException(Component.translatable("commands.urban.error.too_many_requests"));
|
||||
|
||||
final Bot bot = context.bot;
|
||||
|
||||
|
@ -50,12 +55,12 @@ public class UrbanCommand extends Command {
|
|||
|
||||
final Gson gson = new Gson();
|
||||
|
||||
bot.executorService.submit(() -> {
|
||||
bot.executorService.execute(() -> {
|
||||
try {
|
||||
final URL url = new URL(
|
||||
final URL url = new URI(
|
||||
"https://api.urbandictionary.com/v0/define?term=" +
|
||||
URLEncoder.encode(term, StandardCharsets.UTF_8)
|
||||
);
|
||||
).toURL();
|
||||
|
||||
final String jsonOutput = HttpUtilities.getRequest(url);
|
||||
|
||||
|
@ -63,19 +68,19 @@ public class UrbanCommand extends Command {
|
|||
|
||||
final JsonArray list = jsonObject.getAsJsonArray("list");
|
||||
|
||||
if (list.isEmpty()) context.sendOutput(Component.text("No results found").color(NamedTextColor.RED));
|
||||
if (list.isEmpty()) context.sendOutput(Component.translatable("commands.urban.error.no_results", NamedTextColor.RED));
|
||||
|
||||
Component discordComponent = Component.text("*Showing only 3 results because Discord*").append(Component.newline());
|
||||
Component discordComponent = Component.translatable("commands.urban.discord_warning").append(Component.newline());
|
||||
|
||||
int count = 0;
|
||||
int index = 1;
|
||||
for (JsonElement element : list) {
|
||||
for (final JsonElement element : list) {
|
||||
if (count >= 3) break;
|
||||
|
||||
final JsonObject definitionObject = element.getAsJsonObject();
|
||||
|
||||
final String word = definitionObject.get("word").getAsString();
|
||||
final String _definition = definitionObject.get("definition").getAsString();
|
||||
final String originalDefinition = definitionObject.get("definition").getAsString();
|
||||
|
||||
final DecimalFormat formatter = new DecimalFormat("#,###");
|
||||
|
||||
|
@ -84,40 +89,35 @@ public class UrbanCommand extends Command {
|
|||
final String thumbsDown = formatter.format(definitionObject.get("thumbs_down").getAsInt());
|
||||
final String example = definitionObject.get("example").getAsString();
|
||||
|
||||
// whats the best way to implement this?
|
||||
// what's the best way to implement this?
|
||||
// also ohio code warning
|
||||
Component definitionComponent = Component.empty();
|
||||
|
||||
final String definition = _definition.replaceAll("\r\n?", "\n");
|
||||
final String definition = originalDefinition.replaceAll("\r\n?", "\n");
|
||||
|
||||
final String[] splittedDefinition = definition.split("[\\[\\]]");
|
||||
for (int i = 0; i < splittedDefinition.length; i++) {
|
||||
final String[] splitDefinition = definition.split("[\\[\\]]");
|
||||
for (int i = 0; i < splitDefinition.length; i++) {
|
||||
final boolean even = i % 2 == 0;
|
||||
|
||||
final String wordWithDefinition = word + " - " + definition;
|
||||
|
||||
final Component globalHoverEvent = Component.translatable(
|
||||
"""
|
||||
Written by %s
|
||||
Thumbs up: %s
|
||||
Thumbs down: %s
|
||||
Example: %s""",
|
||||
Component.text(author).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
Component.text(thumbsUp).color(NamedTextColor.GREEN),
|
||||
Component.text(thumbsDown).color(NamedTextColor.RED),
|
||||
Component.text(example.replaceAll("\r\n?", "\n")).color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
||||
"commands.urban.hover.info",
|
||||
Component.text(author, bot.colorPalette.string),
|
||||
Component.text(thumbsUp, NamedTextColor.GREEN),
|
||||
Component.text(thumbsDown, NamedTextColor.RED),
|
||||
Component.text(example.replaceAll("\r\n?", "\n"), bot.colorPalette.string)
|
||||
);
|
||||
|
||||
if (even) {
|
||||
definitionComponent = definitionComponent.append(
|
||||
Component
|
||||
.text(splittedDefinition[i])
|
||||
.color(NamedTextColor.GRAY)
|
||||
.text(splitDefinition[i], NamedTextColor.GRAY)
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
globalHoverEvent
|
||||
.append(Component.newline())
|
||||
.append(Component.text("Click here to copy the word and the definition to your clipboard").color(NamedTextColor.GREEN))
|
||||
.append(Component.translatable("commands.urban.hover.copy", NamedTextColor.GREEN))
|
||||
)
|
||||
)
|
||||
.clickEvent(ClickEvent.copyToClipboard(wordWithDefinition))
|
||||
|
@ -126,17 +126,23 @@ public class UrbanCommand extends Command {
|
|||
final String command = context.prefix +
|
||||
name +
|
||||
" " +
|
||||
splittedDefinition[i];
|
||||
splitDefinition[i];
|
||||
|
||||
definitionComponent = definitionComponent.append(
|
||||
Component
|
||||
.text(splittedDefinition[i])
|
||||
.text(splitDefinition[i])
|
||||
.style(Style.style(TextDecoration.UNDERLINED))
|
||||
.hoverEvent(
|
||||
HoverEvent.showText(
|
||||
globalHoverEvent
|
||||
.append(Component.newline())
|
||||
.append(Component.text("Click here to run " + command).color(NamedTextColor.GREEN))
|
||||
.append(
|
||||
Component.translatable(
|
||||
"commands.urban.hover.run",
|
||||
NamedTextColor.GREEN,
|
||||
Component.text(command)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
.clickEvent(
|
||||
|
@ -151,11 +157,12 @@ public class UrbanCommand extends Command {
|
|||
if (discord) {
|
||||
discordComponent = discordComponent
|
||||
.append(
|
||||
Component.translatable(
|
||||
"%s - %s",
|
||||
Component.text(word).color(NamedTextColor.GRAY),
|
||||
definitionComponent
|
||||
).color(NamedTextColor.DARK_GRAY)
|
||||
Component.translatable(
|
||||
"%s - %s",
|
||||
NamedTextColor.DARK_GRAY,
|
||||
Component.text(word, NamedTextColor.GRAY),
|
||||
definitionComponent
|
||||
)
|
||||
)
|
||||
.append(Component.newline());
|
||||
|
||||
|
@ -163,10 +170,11 @@ public class UrbanCommand extends Command {
|
|||
} else {
|
||||
final Component component = Component.translatable(
|
||||
"[%s] %s - %s",
|
||||
Component.text(index).color(NamedTextColor.GREEN),
|
||||
Component.text(word).color(NamedTextColor.GRAY),
|
||||
NamedTextColor.DARK_GRAY,
|
||||
Component.text(index, NamedTextColor.GREEN),
|
||||
Component.text(word, NamedTextColor.GRAY),
|
||||
definitionComponent
|
||||
).color(NamedTextColor.DARK_GRAY);
|
||||
);
|
||||
|
||||
context.sendOutput(component);
|
||||
}
|
||||
|
@ -175,13 +183,13 @@ public class UrbanCommand extends Command {
|
|||
}
|
||||
|
||||
if (discord && !list.isEmpty()) context.sendOutput(discordComponent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
context.sendOutput(Component.text(e.toString()).color(NamedTextColor.RED));
|
||||
} catch (final Exception e) {
|
||||
bot.logger.error(e);
|
||||
context.sendOutput(Component.text(e.toString(), NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
|
||||
requestsPerSecond++;
|
||||
requestsPerSecond.getAndIncrement();
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
package me.chayapak1.chomens_bot.commands;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.command.Command;
|
||||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.command.contexts.ConsoleCommandContext;
|
||||
import me.chayapak1.chomens_bot.command.contexts.DiscordCommandContext;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
|
@ -12,27 +12,35 @@ public class ValidateCommand extends Command {
|
|||
public ValidateCommand () {
|
||||
super(
|
||||
"validate",
|
||||
"Validates a hash",
|
||||
new String[] { "" },
|
||||
new String[] { "checkhash" },
|
||||
TrustLevel.TRUSTED,
|
||||
false
|
||||
TrustLevel.TRUSTED
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
public Component execute (final CommandContext context) {
|
||||
// <red>Trusted - 1
|
||||
// <dark_red>Admin - 2
|
||||
// ...
|
||||
final Component trustLevelComponent = context.trustLevel.component
|
||||
.append(Component.text(" - "))
|
||||
.append(Component.text(context.trustLevel.level));
|
||||
|
||||
final String[] fullArgs = context.fullArgs;
|
||||
|
||||
if (fullArgs.length == 0) return null;
|
||||
|
||||
final String hash = fullArgs[0];
|
||||
|
||||
if (bot.hashing.isCorrectHash(hash, context.userInputCommandName, context.sender)) return Component.text("Valid hash").color(NamedTextColor.GREEN);
|
||||
else if (bot.hashing.isCorrectOwnerHash(hash, context.userInputCommandName, context.sender)) return Component.text("Valid OwnerHash").color(NamedTextColor.GREEN);
|
||||
|
||||
return null;
|
||||
if (context instanceof DiscordCommandContext) return Component
|
||||
.translatable(
|
||||
"commands.validate.discord",
|
||||
NamedTextColor.GREEN,
|
||||
trustLevelComponent
|
||||
);
|
||||
else if (context instanceof ConsoleCommandContext) return Component
|
||||
.translatable("commands.validate.console", NamedTextColor.GREEN);
|
||||
else return Component.translatable(
|
||||
context.sender.persistingData.authenticatedTrustLevel != TrustLevel.PUBLIC
|
||||
? "commands.validate.player_authenticated"
|
||||
: "commands.validate.player",
|
||||
NamedTextColor.GREEN,
|
||||
trustLevelComponent
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,31 +7,26 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.util.HttpUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
public class WeatherCommand extends Command {
|
||||
public WeatherCommand () {
|
||||
super(
|
||||
"weather",
|
||||
"Shows the weather in a place",
|
||||
new String[] { "<location>" },
|
||||
new String[] {},
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
TrustLevel.PUBLIC
|
||||
);
|
||||
}
|
||||
|
||||
public Component execute (CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String location = context.getString(true, true);
|
||||
|
@ -39,29 +34,23 @@ public class WeatherCommand extends Command {
|
|||
final Gson gson = new Gson();
|
||||
|
||||
try {
|
||||
final URL url = new URL(
|
||||
final URL url = new URI(
|
||||
"https://api.weatherapi.com/v1/current.json?key=" + bot.config.weatherApiKey + "&q=" +
|
||||
URLEncoder.encode(
|
||||
location,
|
||||
location,
|
||||
StandardCharsets.UTF_8
|
||||
)
|
||||
+ "&aqi=no"
|
||||
);
|
||||
).toURL();
|
||||
|
||||
final String jsonOutput = HttpUtilities.getRequest(url);
|
||||
|
||||
final JsonObject jsonObject = gson.fromJson(jsonOutput, JsonObject.class);
|
||||
|
||||
final ZoneId zoneId = ZoneId.of(jsonObject.get("location").getAsJsonObject().get("tz_id").getAsString());
|
||||
final ZonedDateTime zonedDateTime = ZonedDateTime.now(zoneId);
|
||||
|
||||
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm:ss a");
|
||||
final String time = zonedDateTime.format(formatter);
|
||||
|
||||
return Component.translatable(
|
||||
"Weather forecast for %s, %s:\n%s (%s), feels like %s (%s)\nTime: %s",
|
||||
Component.text(jsonObject.get("location").getAsJsonObject().get("name").getAsString()).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
Component.text(jsonObject.get("location").getAsJsonObject().get("country").getAsString()).color(ColorUtilities.getColorByString(bot.config.colorPalette.string)),
|
||||
"commands.weather.info",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(jsonObject.get("location").getAsJsonObject().get("name").getAsString(), bot.colorPalette.string),
|
||||
Component.text(jsonObject.get("location").getAsJsonObject().get("country").getAsString(), bot.colorPalette.string),
|
||||
Component
|
||||
.empty()
|
||||
.append(
|
||||
|
@ -73,7 +62,7 @@ public class WeatherCommand extends Command {
|
|||
.get("temp_c")
|
||||
.getAsString() + "°C"
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
||||
.color(bot.colorPalette.secondary)
|
||||
),
|
||||
Component
|
||||
.text(
|
||||
|
@ -83,7 +72,7 @@ public class WeatherCommand extends Command {
|
|||
.get("temp_f")
|
||||
.getAsString() + "°F"
|
||||
)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary)),
|
||||
.color(bot.colorPalette.secondary),
|
||||
Component
|
||||
.text(
|
||||
jsonObject
|
||||
|
@ -102,10 +91,49 @@ public class WeatherCommand extends Command {
|
|||
.getAsString() + "°F"
|
||||
)
|
||||
.color(NamedTextColor.GREEN),
|
||||
Component.text(time).color(ColorUtilities.getColorByString(bot.config.colorPalette.string))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
} catch (Exception e) {
|
||||
throw new CommandException(Component.text("Location \"" + location + "\" not found"));
|
||||
Component
|
||||
.text(
|
||||
jsonObject
|
||||
.get("current")
|
||||
.getAsJsonObject()
|
||||
.get("condition")
|
||||
.getAsJsonObject()
|
||||
.get("text")
|
||||
.getAsString()
|
||||
)
|
||||
.color(bot.colorPalette.string),
|
||||
Component
|
||||
.text(
|
||||
jsonObject
|
||||
.get("current")
|
||||
.getAsJsonObject()
|
||||
.get("cloud")
|
||||
.getAsInt()
|
||||
)
|
||||
.append(Component.text("%"))
|
||||
.color(bot.colorPalette.number),
|
||||
Component
|
||||
.text(
|
||||
jsonObject
|
||||
.get("current")
|
||||
.getAsJsonObject()
|
||||
.get("humidity")
|
||||
.getAsInt()
|
||||
)
|
||||
.append(Component.text("%"))
|
||||
.color(bot.colorPalette.number),
|
||||
Component
|
||||
.text(
|
||||
jsonObject
|
||||
.get("location")
|
||||
.getAsJsonObject()
|
||||
.get("localtime")
|
||||
.getAsString()
|
||||
)
|
||||
.color(bot.colorPalette.string)
|
||||
);
|
||||
} catch (final Exception e) {
|
||||
throw new CommandException(Component.translatable("commands.weather.error.not_found", Component.text(location)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.JoinConfiguration;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
|
@ -17,19 +16,17 @@ public class WhitelistCommand extends Command {
|
|||
public WhitelistCommand () {
|
||||
super(
|
||||
"whitelist",
|
||||
"Manages whitelist",
|
||||
new String[] { "enable", "disable", "add <player>", "remove <index>", "clear", "list" },
|
||||
new String[] {},
|
||||
TrustLevel.OWNER,
|
||||
false
|
||||
TrustLevel.ADMIN
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Component execute(CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String action = context.getString(false, true, true);
|
||||
final String action = context.getAction();
|
||||
|
||||
switch (action) {
|
||||
case "enable" -> {
|
||||
|
@ -37,14 +34,14 @@ public class WhitelistCommand extends Command {
|
|||
|
||||
bot.whitelist.enable();
|
||||
|
||||
return Component.text("Enabled whitelist").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.whitelist.enable", bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "disable" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
||||
bot.whitelist.disable();
|
||||
|
||||
return Component.text("Disabled whitelist").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.whitelist.disable", bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "add" -> {
|
||||
final String player = context.getString(true, true);
|
||||
|
@ -52,9 +49,10 @@ public class WhitelistCommand extends Command {
|
|||
bot.whitelist.add(player);
|
||||
|
||||
return Component.translatable(
|
||||
"Added %s to the whitelist",
|
||||
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
"commands.whitelist.add",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(player, bot.colorPalette.username)
|
||||
);
|
||||
}
|
||||
case "remove" -> {
|
||||
try {
|
||||
|
@ -63,11 +61,12 @@ public class WhitelistCommand extends Command {
|
|||
final String player = bot.whitelist.remove(index);
|
||||
|
||||
return Component.translatable(
|
||||
"Removed %s from the whitelist",
|
||||
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
} catch (IndexOutOfBoundsException | IllegalArgumentException | NullPointerException ignored) {
|
||||
throw new CommandException(Component.text("Invalid index"));
|
||||
"commands.whitelist.remove",
|
||||
bot.colorPalette.defaultColor,
|
||||
Component.text(player, bot.colorPalette.username)
|
||||
);
|
||||
} catch (final IndexOutOfBoundsException | IllegalArgumentException | NullPointerException e) {
|
||||
throw new CommandException(Component.translatable("commands.generic.error.invalid_index"));
|
||||
}
|
||||
}
|
||||
case "clear" -> {
|
||||
|
@ -75,7 +74,7 @@ public class WhitelistCommand extends Command {
|
|||
|
||||
bot.whitelist.clear();
|
||||
|
||||
return Component.text("Cleared the whitelist").color(ColorUtilities.getColorByString(bot.config.colorPalette.defaultColor));
|
||||
return Component.translatable("commands.whitelist.clear", bot.colorPalette.defaultColor);
|
||||
}
|
||||
case "list" -> {
|
||||
context.checkOverloadArgs(1);
|
||||
|
@ -83,29 +82,30 @@ public class WhitelistCommand extends Command {
|
|||
final List<Component> playersComponent = new ArrayList<>();
|
||||
|
||||
int index = 0;
|
||||
for (String player : bot.whitelist.list) {
|
||||
for (final String player : bot.whitelist.list) {
|
||||
playersComponent.add(
|
||||
Component.translatable(
|
||||
"%s › %s",
|
||||
Component.text(index).color(ColorUtilities.getColorByString(bot.config.colorPalette.number)),
|
||||
Component.text(player).color(ColorUtilities.getColorByString(bot.config.colorPalette.username))
|
||||
).color(NamedTextColor.DARK_GRAY)
|
||||
NamedTextColor.DARK_GRAY,
|
||||
Component.text(index, bot.colorPalette.number),
|
||||
Component.text(player, bot.colorPalette.username)
|
||||
)
|
||||
);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return Component.empty()
|
||||
.append(Component.text("Whitelisted players ").color(NamedTextColor.GREEN))
|
||||
.append(Component.text("(").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(bot.whitelist.list.size()).color(NamedTextColor.GRAY))
|
||||
.append(Component.text(")").color(NamedTextColor.DARK_GRAY))
|
||||
.append(Component.translatable("commands.whitelist.whitelisted_players_text", NamedTextColor.GREEN))
|
||||
.append(Component.text("(", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.text(bot.whitelist.list.size(), NamedTextColor.GRAY))
|
||||
.append(Component.text(")", NamedTextColor.DARK_GRAY))
|
||||
.append(Component.newline())
|
||||
.append(
|
||||
Component.join(JoinConfiguration.newlines(), playersComponent)
|
||||
);
|
||||
}
|
||||
default -> throw new CommandException(Component.text("Invalid action"));
|
||||
default -> throw new CommandException(Component.translatable("commands.generic.error.invalid_action"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,44 +9,46 @@ import me.chayapak1.chomens_bot.command.Command;
|
|||
import me.chayapak1.chomens_bot.command.CommandContext;
|
||||
import me.chayapak1.chomens_bot.command.CommandException;
|
||||
import me.chayapak1.chomens_bot.command.TrustLevel;
|
||||
import me.chayapak1.chomens_bot.util.ColorUtilities;
|
||||
import me.chayapak1.chomens_bot.data.chat.ChatPacketType;
|
||||
import me.chayapak1.chomens_bot.util.HTMLUtilities;
|
||||
import me.chayapak1.chomens_bot.util.HttpUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.format.NamedTextColor;
|
||||
import net.kyori.adventure.text.format.Style;
|
||||
import net.kyori.adventure.text.format.TextDecoration;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.net.URLEncoder;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public class WikipediaCommand extends Command {
|
||||
public static final String pageIDStringURL = "https://en.wikipedia.org/w/api.php?prop=info%%7Cpageprops&inprop=url&ppprop=disambiguation&titles=%s&format=json&redirects=&action=query&origin=*&";
|
||||
public static final String outputStringURL = "https://en.wikipedia.org/w/api.php?prop=extracts&explaintext=&exintro=&pageids=%d&format=json&redirects=&action=query&origin=*&";
|
||||
public static final String outputStringURL = "https://en.wikipedia.org/w/api.php?prop=extracts&exintro=&pageids=%d&format=json&redirects=&action=query&origin=*&";
|
||||
|
||||
public WikipediaCommand () {
|
||||
super(
|
||||
"wikipedia",
|
||||
"Wikipedia in Minecraft",
|
||||
new String[] { "<page>" },
|
||||
new String[] { "wiki" },
|
||||
TrustLevel.PUBLIC,
|
||||
false
|
||||
false,
|
||||
new ChatPacketType[] { ChatPacketType.DISGUISED }
|
||||
);
|
||||
}
|
||||
|
||||
public Component execute (CommandContext context) throws CommandException {
|
||||
public Component execute (final CommandContext context) throws CommandException {
|
||||
final Bot bot = context.bot;
|
||||
|
||||
final String page = context.getString(true, true);
|
||||
|
||||
final Gson gson = new Gson();
|
||||
|
||||
bot.executorService.submit(() -> {
|
||||
bot.executorService.execute(() -> {
|
||||
try {
|
||||
Component component = Component.empty();
|
||||
|
||||
final URL pageIDUrl = new URL(String.format(pageIDStringURL, URLEncoder.encode(page, StandardCharsets.UTF_8)));
|
||||
final URL pageIDUrl = new URI(String.format(pageIDStringURL, URLEncoder.encode(page, StandardCharsets.UTF_8))).toURL();
|
||||
|
||||
final JsonObject pageIDJsonOutput = gson.fromJson(HttpUtilities.getRequest(pageIDUrl), JsonObject.class);
|
||||
|
||||
|
@ -56,7 +58,7 @@ public class WikipediaCommand extends Command {
|
|||
if (redirectsElement != null) {
|
||||
final JsonArray normalized = redirectsElement.getAsJsonArray();
|
||||
|
||||
for (JsonElement element : normalized) {
|
||||
for (final JsonElement element : normalized) {
|
||||
final JsonObject redirect = element.getAsJsonObject();
|
||||
|
||||
final String redirectedTo = redirect.get("to").getAsString();
|
||||
|
@ -79,11 +81,15 @@ public class WikipediaCommand extends Command {
|
|||
final int pageID = Integer.parseInt(pages.entrySet().iterator().next().getKey());
|
||||
|
||||
if (pageID == -1) {
|
||||
context.sendOutput(Component.text("Cannot find page: " + page).color(NamedTextColor.RED));
|
||||
return;
|
||||
throw new CommandException(
|
||||
Component.translatable(
|
||||
"commands.wikipedia.error.not_found",
|
||||
Component.text(page)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
final URL outputUrl = new URL(String.format(outputStringURL, pageID));
|
||||
final URL outputUrl = new URI(String.format(outputStringURL, pageID)).toURL();
|
||||
|
||||
final JsonObject outputJsonOutput = gson.fromJson(HttpUtilities.getRequest(outputUrl), JsonObject.class);
|
||||
|
||||
|
@ -93,7 +99,9 @@ public class WikipediaCommand extends Command {
|
|||
.getAsJsonObject(String.valueOf(pageID));
|
||||
|
||||
final String title = pageOutput.get("title").getAsString();
|
||||
final String extract = pageOutput.get("extract").getAsString();
|
||||
final String extracted = HTMLUtilities.toFormattingCodes(pageOutput.get("extract").getAsString());
|
||||
|
||||
if (extracted == null) throw new CommandException(Component.translatable("commands.wikipedia.error.no_contents"));
|
||||
|
||||
component = component
|
||||
.append(
|
||||
|
@ -102,18 +110,20 @@ public class WikipediaCommand extends Command {
|
|||
.style(
|
||||
Style.style()
|
||||
.decorate(TextDecoration.BOLD)
|
||||
.color(ColorUtilities.getColorByString(bot.config.colorPalette.secondary))
|
||||
.color(bot.colorPalette.secondary)
|
||||
)
|
||||
)
|
||||
.append(Component.newline())
|
||||
.append(Component.text(extract).color(NamedTextColor.GREEN));
|
||||
.append(Component.text(extracted, NamedTextColor.GREEN));
|
||||
|
||||
context.sendOutput(component);
|
||||
} catch (NumberFormatException e) {
|
||||
context.sendOutput(Component.text("Failed parsing page ID").color(NamedTextColor.RED));
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
context.sendOutput(Component.text(e.toString()).color(NamedTextColor.RED));
|
||||
} catch (final NumberFormatException e) {
|
||||
context.sendOutput(Component.translatable("commands.wikipedia.error.fail_page_id_parse", NamedTextColor.RED));
|
||||
bot.logger.error(e);
|
||||
} catch (final CommandException e) {
|
||||
context.sendOutput(e.message.color(NamedTextColor.RED));
|
||||
} catch (final Exception e) {
|
||||
context.sendOutput(Component.text(e.toString(), NamedTextColor.RED));
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
|
||||
|
||||
public record CommandLoop (
|
||||
String command,
|
||||
int interval
|
||||
) {}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
|
||||
public class FilteredPlayer {
|
||||
public final String playerName;
|
||||
public final boolean regex;
|
||||
public final boolean ignoreCase;
|
||||
|
||||
public FilteredPlayer (
|
||||
String playerName,
|
||||
boolean regex,
|
||||
boolean ignoreCase
|
||||
) {
|
||||
this.playerName = playerName;
|
||||
this.regex = regex;
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
|
||||
// https://gist.github.com/kaecy/286f8ad334aec3fcb588516feb727772#file-message-java
|
||||
public class IRCMessage {
|
||||
public String origin;
|
||||
public String nickName;
|
||||
public String command;
|
||||
public String channel;
|
||||
public String content;
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
|
||||
public class Mail {
|
||||
public final String sentBy;
|
||||
public final String sentTo;
|
||||
public final long timeSent;
|
||||
public final String server;
|
||||
public final String contents;
|
||||
|
||||
public Mail (
|
||||
String sentBy,
|
||||
String sentTo,
|
||||
long timeSent,
|
||||
String server,
|
||||
String contents
|
||||
) {
|
||||
this.sentBy = sentBy;
|
||||
this.sentTo = sentTo;
|
||||
this.timeSent = timeSent;
|
||||
this.server = server;
|
||||
this.contents = contents;
|
||||
}
|
||||
}
|
|
@ -1,43 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
|
||||
import org.geysermc.mcprotocollib.auth.GameProfile;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.PlayerListEntry;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.entity.player.GameMode;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.security.PublicKey;
|
||||
|
||||
public class PlayerEntry {
|
||||
public final GameProfile profile;
|
||||
public GameMode gamemode;
|
||||
public int latency;
|
||||
public Component displayName;
|
||||
public final long expiresAt;
|
||||
public PublicKey publicKey;
|
||||
public final byte[] keySignature;
|
||||
public boolean listed;
|
||||
|
||||
public PlayerEntry(
|
||||
GameProfile profile,
|
||||
GameMode gamemode,
|
||||
int latency,
|
||||
Component displayName,
|
||||
long expiresAt,
|
||||
PublicKey publicKey,
|
||||
byte[] keySignature,
|
||||
boolean listed
|
||||
) {
|
||||
this.profile = profile;
|
||||
this.gamemode = gamemode;
|
||||
this.latency = latency;
|
||||
this.displayName = displayName;
|
||||
this.expiresAt = expiresAt;
|
||||
this.publicKey = publicKey;
|
||||
this.keySignature = keySignature;
|
||||
this.listed = listed;
|
||||
}
|
||||
|
||||
public PlayerEntry(PlayerListEntry entry) {
|
||||
this(entry.getProfile(), entry.getGameMode(), entry.getLatency(), entry.getDisplayName(), entry.getExpiresAt(), entry.getPublicKey(), entry.getKeySignature(), entry.isListed());
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
|
||||
public record Rotation (
|
||||
float yaw,
|
||||
float pitch
|
||||
) {}
|
|
@ -1,40 +0,0 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.CollisionRule;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.NameTagVisibility;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.scoreboard.TeamColor;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class Team {
|
||||
public String teamName;
|
||||
public Component displayName;
|
||||
public boolean friendlyFire;
|
||||
public boolean seeFriendlyInvisibles;
|
||||
public NameTagVisibility nametagVisibility;
|
||||
public CollisionRule collisionRule;
|
||||
public TeamColor color;
|
||||
public Component prefix;
|
||||
public Component suffix;
|
||||
|
||||
public Team (
|
||||
String teamName,
|
||||
Component displayName,
|
||||
boolean friendlyFire,
|
||||
boolean seeFriendlyInvisibles,
|
||||
NameTagVisibility nametagVisibility,
|
||||
CollisionRule collisionRule,
|
||||
TeamColor color,
|
||||
Component prefix,
|
||||
Component suffix
|
||||
) {
|
||||
this.teamName = teamName;
|
||||
this.displayName = displayName;
|
||||
this.friendlyFire = friendlyFire;
|
||||
this.seeFriendlyInvisibles = seeFriendlyInvisibles;
|
||||
this.nametagVisibility = nametagVisibility;
|
||||
this.collisionRule = collisionRule;
|
||||
this.color = color;
|
||||
this.prefix = prefix;
|
||||
this.suffix = suffix;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
package me.chayapak1.chomens_bot.data.bossbar;
|
||||
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.BossBarColor;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.BossBarDivision;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
|
@ -15,11 +15,11 @@ public class BossBar {
|
|||
public float health;
|
||||
|
||||
public BossBar (
|
||||
UUID uuid,
|
||||
Component title,
|
||||
BossBarColor color,
|
||||
BossBarDivision division,
|
||||
float health
|
||||
final UUID uuid,
|
||||
final Component title,
|
||||
final BossBarColor color,
|
||||
final BossBarDivision division,
|
||||
final float health
|
||||
) {
|
||||
this.uuid = uuid;
|
||||
this.title = title;
|
||||
|
@ -28,4 +28,3 @@ public class BossBar {
|
|||
this.health = health;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +1,21 @@
|
|||
package me.chayapak1.chomens_bot.data;
|
||||
package me.chayapak1.chomens_bot.data.bossbar;
|
||||
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.util.SNBTUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.BossBarColor;
|
||||
import org.geysermc.mcprotocollib.protocol.data.game.BossBarDivision;
|
||||
import me.chayapak1.chomens_bot.Bot;
|
||||
import me.chayapak1.chomens_bot.util.ComponentUtilities;
|
||||
import net.kyori.adventure.text.Component;
|
||||
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class BotBossBar extends BossBar {
|
||||
public UUID uuid = UUID.randomUUID(); // the random uuid will be temporary
|
||||
public UUID uuid = UUID.randomUUID(); // temporary
|
||||
|
||||
public final Component secret = Component.text(Math.random() * 69420);
|
||||
public final Component secret = Component
|
||||
.translatable(
|
||||
"",
|
||||
Component.text(UUID.randomUUID().toString())
|
||||
);
|
||||
|
||||
public boolean gotSecret = false;
|
||||
|
||||
|
@ -26,15 +29,15 @@ public class BotBossBar extends BossBar {
|
|||
private long max;
|
||||
private int value;
|
||||
|
||||
public BotBossBar(
|
||||
Component title,
|
||||
String players,
|
||||
BossBarColor color,
|
||||
BossBarDivision division,
|
||||
boolean visible,
|
||||
long max,
|
||||
int value,
|
||||
Bot bot
|
||||
public BotBossBar (
|
||||
final Component title,
|
||||
final String players,
|
||||
final BossBarColor color,
|
||||
final BossBarDivision division,
|
||||
final boolean visible,
|
||||
final long max,
|
||||
final int value,
|
||||
final Bot bot
|
||||
) {
|
||||
super(null, title, color, division, value);
|
||||
this.players = players;
|
||||
|
@ -43,18 +46,16 @@ public class BotBossBar extends BossBar {
|
|||
this.bot = bot;
|
||||
}
|
||||
|
||||
public Component title() {
|
||||
public Component title () {
|
||||
return title;
|
||||
}
|
||||
|
||||
public void setTitle(Component title) {
|
||||
public void setTitle (final Component title) {
|
||||
setTitle(title, false);
|
||||
}
|
||||
|
||||
public void setTitle(Component title, boolean force) {
|
||||
if (!gotSecret) return;
|
||||
|
||||
if (ComponentUtilities.isEqual(this.title, title) && !force) return;
|
||||
public void setTitle (final Component title, final boolean force) {
|
||||
if ((this.title.equals(title) || !gotSecret) && !force) return;
|
||||
|
||||
if (bot.bossbar.actionBar) {
|
||||
bot.chat.actionBar(title, players);
|
||||
|
@ -64,25 +65,31 @@ public class BotBossBar extends BossBar {
|
|||
|
||||
this.title = title;
|
||||
|
||||
final String serialized = GsonComponentSerializer.gson().serialize(title);
|
||||
final String serialized = SNBTUtilities.fromComponent(bot.options.useSNBTComponents, title);
|
||||
|
||||
bot.core.run("minecraft:bossbar set " + id + " name " + serialized);
|
||||
|
||||
if (!bot.core.hasRateLimit()) bot.core.run("minecraft:execute as @e[type=minecraft:text_display,tag=" + bot.config.bossBarNamespace + "_" + onlyName + "] run data modify entity @s text set value '" + serialized.replace("\\", "\\\\").replace("'", "\\'") + "'");
|
||||
if (!bot.core.hasRateLimit())
|
||||
bot.core.run(
|
||||
String.format(
|
||||
"minecraft:execute as @e[type=minecraft:text_display,tag=%s_%s] run data modify entity @s text set value %s",
|
||||
bot.config.namespace,
|
||||
onlyName,
|
||||
serialized
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public BossBarColor color(BossBarColor color) {
|
||||
public BossBarColor color (final BossBarColor color) {
|
||||
return color;
|
||||
}
|
||||
|
||||
public void setColor(BossBarColor color) {
|
||||
public void setColor (final BossBarColor color) {
|
||||
setColor(color, false);
|
||||
}
|
||||
|
||||
public void setColor(BossBarColor color, boolean force) {
|
||||
if (!gotSecret) return;
|
||||
|
||||
if (this.color == color && !force) return;
|
||||
public void setColor (final BossBarColor color, final boolean force) {
|
||||
if ((this.color == color || !gotSecret) && !force) return;
|
||||
|
||||
this.color = color;
|
||||
|
||||
|
@ -91,14 +98,14 @@ public class BotBossBar extends BossBar {
|
|||
bot.core.run("minecraft:bossbar set " + id + " color " + (color == BossBarColor.LIME ? "green" : (color == BossBarColor.CYAN ? "blue" : color.name().toLowerCase())));
|
||||
}
|
||||
|
||||
public String players() {
|
||||
public String players () {
|
||||
return players;
|
||||
}
|
||||
|
||||
public void setPlayers(String players) {
|
||||
if (!gotSecret) return;
|
||||
public void setPlayers (final String players) { setPlayers(players, false); }
|
||||
|
||||
if (this.players.equals(players)) return;
|
||||
public void setPlayers (final String players, final boolean force) {
|
||||
if ((this.players.equals(players) || !gotSecret) && !force) return;
|
||||
|
||||
this.players = players;
|
||||
|
||||
|
@ -108,13 +115,13 @@ public class BotBossBar extends BossBar {
|
|||
}
|
||||
|
||||
public BossBarDivision division () { return division; }
|
||||
public void setDivision (BossBarDivision division) {
|
||||
|
||||
public void setDivision (final BossBarDivision division) {
|
||||
setDivision(division, false);
|
||||
}
|
||||
public void setDivision (BossBarDivision _division, boolean force) {
|
||||
if (!gotSecret) return;
|
||||
|
||||
if (this.division == _division && !force) return;
|
||||
public void setDivision (final BossBarDivision _division, final boolean force) {
|
||||
if ((this.division == _division || !gotSecret) && !force) return;
|
||||
|
||||
this.division = _division;
|
||||
|
||||
|
@ -134,13 +141,13 @@ public class BotBossBar extends BossBar {
|
|||
}
|
||||
|
||||
public int value () { return value; }
|
||||
public void setValue (int value) {
|
||||
|
||||
public void setValue (final int value) {
|
||||
setValue(value, false);
|
||||
}
|
||||
public void setValue (int value, boolean force) {
|
||||
if (!gotSecret) return;
|
||||
|
||||
if (this.value == value && !force) return;
|
||||
public void setValue (final int value, final boolean force) {
|
||||
if ((this.value == value || !gotSecret) && !force) return;
|
||||
|
||||
this.value = value;
|
||||
|
||||
|
@ -150,10 +157,13 @@ public class BotBossBar extends BossBar {
|
|||
}
|
||||
|
||||
public boolean visible () { return visible; }
|
||||
public void setVisible (boolean visible) {
|
||||
if (!gotSecret) return;
|
||||
|
||||
if (this.visible == visible) return;
|
||||
public void setVisible (final boolean visible) {
|
||||
setVisible(visible, false);
|
||||
}
|
||||
|
||||
public void setVisible (final boolean visible, final boolean force) {
|
||||
if ((this.visible == visible || !gotSecret) && !force) return;
|
||||
|
||||
this.visible = visible;
|
||||
|
||||
|
@ -163,13 +173,13 @@ public class BotBossBar extends BossBar {
|
|||
}
|
||||
|
||||
public long max () { return max; }
|
||||
public void setMax (long max) {
|
||||
|
||||
public void setMax (final long max) {
|
||||
setMax(max, false);
|
||||
}
|
||||
public void setMax (long max, boolean force) {
|
||||
if (!gotSecret) return;
|
||||
|
||||
if (this.max == max && !force) return;
|
||||
public void setMax (final long max, final boolean force) {
|
||||
if ((this.max == max || !gotSecret) && !force) return;
|
||||
|
||||
this.max = max;
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
package me.chayapak1.chomens_bot.data.chat;
|
||||
|
||||
public enum ChatPacketType {
|
||||
PLAYER,
|
||||
DISGUISED,
|
||||
SYSTEM
|
||||
}
|
|
@ -1,20 +1,7 @@
|
|||
package me.chayapak1.chomens_bot.data.chat;
|
||||
|
||||
import me.chayapak1.chomens_bot.data.PlayerEntry;
|
||||
import me.chayapak1.chomens_bot.data.player.PlayerEntry;
|
||||
import net.kyori.adventure.text.Component;
|
||||
|
||||
public class PlayerMessage {
|
||||
public final PlayerEntry sender;
|
||||
public final Component displayName;
|
||||
public final Component contents;
|
||||
|
||||
public PlayerMessage (
|
||||
PlayerEntry sender,
|
||||
Component displayName,
|
||||
Component contents
|
||||
) {
|
||||
this.sender = sender;
|
||||
this.displayName = displayName;
|
||||
this.contents = contents;
|
||||
}
|
||||
public record PlayerMessage(PlayerEntry sender, Component displayName, Component contents) {
|
||||
}
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package me.chayapak1.chomens_bot.data.chomeNSMod;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public record PayloadMetadata(byte[] nonce, long timestamp) {
|
||||
public static PayloadMetadata deserialize (final ByteBuf buf) {
|
||||
final byte[] nonce = new byte[8];
|
||||
|
||||
buf.readBytes(nonce);
|
||||
|
||||
final long timestamp = buf.readLong();
|
||||
|
||||
return new PayloadMetadata(nonce, timestamp);
|
||||
}
|
||||
|
||||
public void serialize (final ByteBuf buf) {
|
||||
buf.writeBytes(nonce);
|
||||
buf.writeLong(timestamp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals (final Object object) {
|
||||
if (object == null || getClass() != object.getClass()) return false;
|
||||
|
||||
final PayloadMetadata metadata = (PayloadMetadata) object;
|
||||
|
||||
// java is so fucky about byte[]......... i have to use Arrays.equals()
|
||||
return timestamp == metadata.timestamp && Arrays.equals(nonce, metadata.nonce);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String toString () {
|
||||
return "PayloadMetadata{" +
|
||||
"nonce=" + Arrays.toString(nonce) +
|
||||
", timestamp=" + timestamp +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package me.chayapak1.chomens_bot.data.chomeNSMod;
|
||||
|
||||
public enum PayloadState {
|
||||
JOINING,
|
||||
DONE
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
package me.chayapak1.chomens_bot.data.chunk;
|
||||
|
||||
public record ChunkPos(int x, int z) {
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package me.chayapak1.chomens_bot.data.cloop;
|
||||
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
|
||||
public record CommandLoop(
|
||||
String command,
|
||||
long interval,
|
||||
ChronoUnit unit,
|
||||
ScheduledFuture<?> task
|
||||
) { }
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package me.chayapak1.chomens_bot.data.color;
|
||||
|
||||
import me.chayapak1.chomens_bot.Configuration;
|
||||
import net.kyori.adventure.text.format.TextColor;
|
||||
|
||||
import static me.chayapak1.chomens_bot.util.ColorUtilities.getColorByString;
|
||||
|
||||
public class ColorPalette {
|
||||
public final TextColor primary;
|
||||
public final TextColor secondary;
|
||||
public final TextColor defaultColor;
|
||||
public final TextColor username;
|
||||
public final TextColor uuid;
|
||||
public final TextColor string;
|
||||
public final TextColor number;
|
||||
public final TextColor ownerName;
|
||||
|
||||
public ColorPalette (final Configuration.ColorPalette configColorPalette) {
|
||||
this.primary = getColorByString(configColorPalette.primary);
|
||||
this.secondary = getColorByString(configColorPalette.secondary);
|
||||
this.defaultColor = getColorByString(configColorPalette.defaultColor);
|
||||
this.username = getColorByString(configColorPalette.username);
|
||||
this.uuid = getColorByString(configColorPalette.uuid);
|
||||
this.string = getColorByString(configColorPalette.string);
|
||||
this.number = getColorByString(configColorPalette.number);
|
||||
this.ownerName = getColorByString(configColorPalette.ownerName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
package me.chayapak1.chomens_bot.data.entity;
|
||||
|
||||
public record Rotation(
|
||||
float yaw,
|
||||
float pitch
|
||||
) { }
|
|
@ -5,25 +5,12 @@ import me.chayapak1.chomens_bot.Bot;
|
|||
public class EvalFunction {
|
||||
public final String name;
|
||||
|
||||
protected final Bot bot;
|
||||
|
||||
public EvalFunction (
|
||||
String name,
|
||||
Bot bot
|
||||
) {
|
||||
public EvalFunction (final String name) {
|
||||
this.name = name;
|
||||
this.bot = bot;
|
||||
}
|
||||
|
||||
public Output execute (Object ...args) throws Exception { return null; }
|
||||
public Output execute (final Bot bot, final Object... args) throws Exception { return null; }
|
||||
|
||||
public static class Output {
|
||||
public final String message;
|
||||
public final boolean parseJSON;
|
||||
|
||||
public Output (String message, boolean parseJSON) {
|
||||
this.message = message;
|
||||
this.parseJSON = parseJSON;
|
||||
}
|
||||
public record Output(String message, boolean parseJSON) {
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue