Skip to content

Commit 88c8d4a

Browse files
committed
Finishing touches
1 parent d77f49d commit 88c8d4a

File tree

3 files changed

+83
-92
lines changed

3 files changed

+83
-92
lines changed

src/main/kotlin/io/github/arkosammy12/compsmpdiscordbot/CompSMPDiscordBot.kt

Lines changed: 15 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import io.github.arkosammy12.monkeyconfig.managers.getRawNumberSettingValue
1313
import io.github.arkosammy12.monkeyconfig.managers.getRawStringSettingValue
1414
import io.github.arkosammy12.monkeyutils.registrars.DefaultConfigRegistrar
1515
import kotlinx.coroutines.Job
16-
import kotlinx.coroutines.cancelAndJoin
16+
import kotlinx.coroutines.cancelChildren
1717
import kotlinx.coroutines.runBlocking
1818
import net.fabricmc.api.DedicatedServerModInitializer
1919
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
@@ -31,42 +31,25 @@ object CompSMPDiscordBot : DedicatedServerModInitializer {
3131
lateinit var botJob: Job
3232

3333
val CONFIG_MANAGER: ConfigManager = tomlConfigManager(MOD_ID, FabricLoader.getInstance().configDir.resolve("compsmpdiscordbot.toml")) {
34-
ConfigUtils.BOT_TOKEN = stringSetting("bot_token", "0") {
35-
36-
}
37-
38-
ConfigUtils.GUILD_ID = numberSetting("guild_id", 0L) {
39-
40-
}
41-
ConfigUtils.COMPSMP_ADMIN_ROLE_ID = numberSetting("compsmp_admin_role_id", 0L) {
42-
43-
}
44-
34+
ConfigUtils.BOT_TOKEN = stringSetting("bot_token", "0") {}
35+
ConfigUtils.GUILD_ID = numberSetting("guild_id", 0L) {}
36+
ConfigUtils.COMPSMP_ADMIN_ROLE_ID = numberSetting("compsmp_admin_role_id", 0L) {}
4537
section("application_approval") {
46-
ConfigUtils.APPLICATION_CHANNEL_ID = numberSetting("application_channel_id", 0L) {
47-
48-
}
49-
ConfigUtils.APPROVAL_ROLE_ID = numberSetting("approval_role_id", 0L) {
50-
51-
}
52-
ConfigUtils.APPROVAL_EMOJI_ID = numberSetting("approval_emoji_id", 0L) {
53-
54-
}
55-
ConfigUtils.APPROVAL_EMOJI_NAME = stringSetting("approval_emoji_name", "Approved") {
56-
57-
}
58-
38+
ConfigUtils.APPLICATION_CHANNEL_ID = numberSetting("application_channel_id", 0L) {}
39+
ConfigUtils.APPROVAL_ROLE_ID = numberSetting("approval_role_id", 0L) {}
40+
ConfigUtils.APPROVAL_EMOJI_ID = numberSetting("approval_emoji_id", 0L) {}
41+
ConfigUtils.APPROVAL_EMOJI_NAME = stringSetting("approval_emoji_name", "Approved") {}
5942
}
6043
ConfigUtils.CHAT_COMMANDS = stringMapSection("chat_commands") {
6144
addDefaultEntry("ping" to "pong")
45+
addDefaultEntry("hello" to "world!")
6246
onUpdated = {
6347
runBlocking {
6448
bot.unloadExtension(ReloadableChatCommandsExtension.NAME)
6549
bot.loadExtension(ReloadableChatCommandsExtension.NAME)
6650
}
6751
}
6852
}
69-
7053
}
7154

7255
override fun onInitializeServer() {
@@ -86,12 +69,13 @@ object CompSMPDiscordBot : DedicatedServerModInitializer {
8669
private fun onServerStopping(server: MinecraftServer) {
8770
runBlocking {
8871
bot.close()
89-
botJob.cancelAndJoin()
72+
botJob.cancelChildren()
73+
botJob.cancel()
9074
}
9175

9276
}
9377

94-
fun createBot(token: String): ExtensibleBot {
78+
private fun createBot(token: String): ExtensibleBot {
9579
return runBlocking {
9680
ExtensibleBot(token) {
9781
chatCommands {
@@ -101,23 +85,17 @@ object CompSMPDiscordBot : DedicatedServerModInitializer {
10185
extensions {
10286
add(::AutoApprovalExtension)
10387
add(::ReloadableChatCommandsExtension)
104-
}
105-
about {
106-
107-
}
108-
hooks {
109-
11088
}
11189
@OptIn(PrivilegedIntent::class)
11290
intents {
11391
+Intent.GuildMembers
11492
+Intent.GuildMessageReactions
11593
+Intent.MessageContent
11694
}
117-
cache {
118-
}
95+
11996
}
12097
}
12198
}
12299

123-
}
100+
}
101+

src/main/kotlin/io/github/arkosammy12/compsmpdiscordbot/extensions/AutoApprovalExtension.kt

Lines changed: 54 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import dev.kordex.core.commands.converters.impl.string
1414
import dev.kordex.core.extensions.Extension
1515
import dev.kordex.core.extensions.event
1616
import dev.kordex.core.extensions.publicSlashCommand
17-
import dev.kordex.core.i18n.types.Key
17+
import dev.kordex.core.i18n.toKey
1818
import io.github.arkosammy12.compsmpdiscordbot.CompSMPDiscordBot
1919
import io.github.arkosammy12.compsmpdiscordbot.config.ConfigUtils
2020
import io.github.arkosammy12.monkeyconfig.managers.getRawNumberSettingValue
@@ -26,24 +26,28 @@ import io.ktor.client.plugins.timeout
2626
import io.ktor.client.request.get
2727
import io.ktor.client.statement.HttpResponse
2828
import io.ktor.http.HttpMethod
29-
import io.ktor.http.HttpStatusCode
3029
import io.ktor.http.URLBuilder
30+
import io.ktor.http.isSuccess
3131
import kotlinx.serialization.json.Json
3232
import kotlinx.serialization.json.JsonObject
3333
import kotlinx.serialization.json.jsonObject
3434
import kotlinx.serialization.json.jsonPrimitive
3535
import java.util.UUID
3636

37-
class AutoApprovalExtension() : Extension() {
37+
class AutoApprovalExtension : Extension() {
3838

39-
override val name = NAME
39+
override val name: String = NAME
4040

41-
42-
val adminRoleId: () -> Long = { CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.COMPSMP_ADMIN_ROLE_ID)!! }
43-
val applicationChannelId: () -> Long = { CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.APPLICATION_CHANNEL_ID)!! }
44-
val approvalEmojiId: () -> Long = { CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.APPROVAL_EMOJI_ID)!! }
45-
val approvalRoleId: () -> Long = { CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.APPROVAL_ROLE_ID)!! }
46-
val approvalEmojiName: () -> String = { CompSMPDiscordBot.CONFIG_MANAGER.getRawStringSettingValue(ConfigUtils.APPROVAL_EMOJI_NAME)!! }
41+
val adminRoleId: Long
42+
get() = CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.COMPSMP_ADMIN_ROLE_ID)!!
43+
val applicationChannelId: Long
44+
get() = CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.APPLICATION_CHANNEL_ID)!!
45+
val approvalEmojiId: Long
46+
get() = CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.APPROVAL_EMOJI_ID)!!
47+
val approvalRoleId: Long
48+
get() = CompSMPDiscordBot.CONFIG_MANAGER.getRawNumberSettingValue(ConfigUtils.APPROVAL_ROLE_ID)!!
49+
val approvalEmojiName: String
50+
get() = CompSMPDiscordBot.CONFIG_MANAGER.getRawStringSettingValue(ConfigUtils.APPROVAL_EMOJI_NAME)!!
4751
val httpClient: HttpClient by lazy {
4852
HttpClient()
4953
}
@@ -55,9 +59,9 @@ class AutoApprovalExtension() : Extension() {
5559
return@action
5660
}
5761
val applicant: Member = event.messageAuthor?.asMember(CompSMPDiscordBot.guildSnowFlake) ?: return@action
58-
applicant.addRole(Snowflake(approvalRoleId()))
62+
applicant.addRole(Snowflake(approvalRoleId))
63+
CompSMPDiscordBot.LOGGER.info("Successfully approved Discord user ${applicant.username}.")
5964
}
60-
6165
}
6266
this.event<ReactionRemoveEvent> {
6367
action {
@@ -66,26 +70,28 @@ class AutoApprovalExtension() : Extension() {
6670
}
6771
val applicant: Member = event.message.asMessage().author?.asMember(CompSMPDiscordBot.guildSnowFlake) ?: return@action
6872
val applicantRoles: Set<Snowflake> = applicant.roleIds
69-
if (!applicantRoles.any { roleId -> roleId.value.toLong() == approvalRoleId() }) {
73+
if (!applicantRoles.any { roleId -> roleId.value.toLong() == approvalRoleId }) {
7074
return@action
7175
}
72-
val reactionEmoji: ReactionEmoji = ReactionEmoji.Custom(Snowflake(approvalEmojiId()), approvalEmojiName(), false)
76+
val reactionEmoji: ReactionEmoji = ReactionEmoji.Custom(Snowflake(approvalEmojiId), approvalEmojiName, false)
7377
var hasApprovedRoleByOtherAdmin = false
7478
event.message.getReactors(reactionEmoji).filter { user -> user.id != event.user }.collect { user ->
7579
val member: Member = user.asMember(CompSMPDiscordBot.guildSnowFlake)
76-
if (member.roleIds.any {roleId -> roleId.value.toLong() == adminRoleId() }) {
80+
if (member.roleIds.any { roleId -> roleId.value.toLong() == adminRoleId }) {
7781
hasApprovedRoleByOtherAdmin = true
7882
return@collect
7983
}
8084
}
8185
if (!hasApprovedRoleByOtherAdmin) {
82-
applicant.removeRole(Snowflake(approvalRoleId()))
86+
applicant.removeRole(Snowflake(approvalRoleId))
87+
CompSMPDiscordBot.LOGGER.info("Successfully de-approved Discord user ${applicant.username}.")
8388
}
89+
CompSMPDiscordBot.LOGGER.info("Tried to de-approve applicant ${applicant.username} but their message still has $approvalEmojiName reactions from other admins!")
8490
}
8591
}
8692
publicSlashCommand(::FetchProfileArguments) {
87-
name = Key("fetchGameProfile")
88-
description = Key("Fetches a gameprofile for a given Minecraft username")
93+
name = "getGameProfile".toKey()
94+
description = "Retrieves the username and UUID of the specified Minecraft user.".toKey()
8995
guild(CompSMPDiscordBot.guildSnowFlake)
9096
action {
9197
respond {
@@ -96,19 +102,22 @@ class AutoApprovalExtension() : Extension() {
96102
requestTimeoutMillis = 5_000
97103
}
98104
}
99-
if (response.status == HttpStatusCode.OK) {
100-
val json: JsonObject = Json.parseToJsonElement(response.body()).jsonObject
101-
val rawUuid: String? = json["id"]?.jsonPrimitive?.content
102-
if (rawUuid == null) {
103-
content = "Error deserializing uuid. Missing field \"id\" from json response!"
104-
} else {
105-
val uuid: UUID = UUID.fromString(addDashesToUuid(rawUuid))
106-
content = "Username: `${username}`. UUID: `$uuid`"
105+
when {
106+
response.isError -> content = "Error retrieving game profile for Minecraft user ${username}: ${response.errorString()}"
107+
response.status.isSuccess() -> {
108+
val json: JsonObject = Json.parseToJsonElement(response.body()).jsonObject
109+
val rawUuid: String? = json["id"]?.jsonPrimitive?.content
110+
val name: String? = json["name"]?.jsonPrimitive?.content
111+
if (rawUuid == null || name == null) {
112+
content = "Error deserializing API json response!"
113+
} else {
114+
val uuid: UUID = UUID.fromString(addDashesToUuid(rawUuid))
115+
content = "Username: `${name}`. UUID: `${uuid}`"
116+
}
117+
}
118+
else -> {
119+
content = "Error retrieving game"
107120
}
108-
} else if (response.isError) {
109-
content = "Error fetching game profile: ${response.errorString()}"
110-
} else {
111-
content = "Error fetching game profile: ${response.status}"
112121
}
113122
}
114123
}
@@ -125,36 +134,37 @@ class AutoApprovalExtension() : Extension() {
125134
return false
126135
}
127136
val reactor: Member = user.asMember(CompSMPDiscordBot.guildSnowFlake)
128-
if (!reactor.roleIds.any { roleId -> roleId.value.toLong() == adminRoleId() }) {
137+
if (!reactor.roleIds.any { roleId -> roleId.value.toLong() == adminRoleId }) {
129138
return false
130139
}
131-
if (message.channelId.value.toLong() != applicationChannelId()) {
140+
if (message.channelId.value.toLong() != applicationChannelId) {
132141
return false
133142
}
134-
if (eventEmoji.id.value.toLong() != approvalEmojiId()) {
143+
if (eventEmoji.id.value.toLong() != approvalEmojiId) {
135144
return false
136145
}
137146
return true
138147
}
139148

140-
private fun addDashesToUuid(uuid: String): String {
141-
val buffer: StringBuffer = StringBuffer(uuid)
142-
buffer.insert(20, '-')
143-
buffer.insert(16, '-')
144-
buffer.insert(12, '-')
145-
buffer.insert(8, '-')
146-
return buffer.toString()
147-
}
148-
149149
inner class FetchProfileArguments() : Arguments() {
150150
val username by string {
151-
name = Key("username")
152-
description = Key("The username of the person you wish to see the Minecraft game profile of.")
151+
name = "username".toKey()
152+
description = "The username of the person you wish to see the Minecraft game profile of.".toKey()
153153
}
154154
}
155155

156156
companion object {
157157
const val NAME = "auto_approval_extension"
158+
159+
private fun addDashesToUuid(uuid: String): String {
160+
val buffer = StringBuffer(uuid)
161+
buffer.insert(20, '-')
162+
buffer.insert(16, '-')
163+
buffer.insert(12, '-')
164+
buffer.insert(8, '-')
165+
return buffer.toString()
166+
}
167+
158168
}
159169

160170
}

src/main/kotlin/io/github/arkosammy12/compsmpdiscordbot/extensions/ReloadableChatCommandsExtension.kt

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package io.github.arkosammy12.compsmpdiscordbot.extensions
22

33
import dev.kordex.core.extensions.Extension
4-
import dev.kordex.core.extensions.chatCommand
5-
import dev.kordex.core.i18n.types.Key
6-
import dev.kordex.core.utils.respond
4+
import dev.kordex.core.extensions.publicSlashCommand
5+
import dev.kordex.core.i18n.generated.CoreTranslations
6+
import dev.kordex.core.i18n.toKey
77
import io.github.arkosammy12.compsmpdiscordbot.CompSMPDiscordBot
88
import io.github.arkosammy12.compsmpdiscordbot.config.ConfigUtils
99
import io.github.arkosammy12.monkeyconfig.base.settings
@@ -15,18 +15,21 @@ class ReloadableChatCommandsExtension : Extension() {
1515

1616
override val name: String = NAME
1717

18-
val configurableCommands: () -> Map<String, String> = {
19-
val mapSection: StringMapSection = CompSMPDiscordBot.CONFIG_MANAGER.getStringMapSection(ConfigUtils.CHAT_COMMANDS)!!
20-
mapSection.settings.stream().collect(Collectors.toMap({ setting -> setting.name }, { setting -> setting.value.raw as String }))
21-
}
18+
val configurableCommands: () -> Map<String, String>
19+
get() = {
20+
val mapSection: StringMapSection = CompSMPDiscordBot.CONFIG_MANAGER.getStringMapSection(ConfigUtils.CHAT_COMMANDS)!!
21+
mapSection.settings.stream().collect(Collectors.toMap({ setting -> setting.name }, { setting -> setting.value.raw as String }))
22+
}
2223

2324
override suspend fun setup() {
2425
for ((commandName, commandContent) in configurableCommands()) {
25-
chatCommand {
26-
name = Key(commandName)
27-
description = Key("This is a placeholder description for chat commands.")
26+
publicSlashCommand {
27+
name = commandName.toKey()
28+
description = CoreTranslations.Commands.defaultDescription
2829
action {
29-
message.respond(commandContent)
30+
respond {
31+
content = commandContent
32+
}
3033
}
3134
}
3235

0 commit comments

Comments
 (0)