Skip to content

Commit

Permalink
Add robust error handling and logging for interactions
Browse files Browse the repository at this point in the history
  • Loading branch information
WinG4merBR committed Dec 28, 2024
1 parent 34bfbc9 commit 39a5f3b
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 30 deletions.
9 changes: 9 additions & 0 deletions foxy/src/main/kotlin/net/cakeyfox/foxy/FoxyInstance.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.ktor.client.engine.cio.*
import io.ktor.client.plugins.*
import io.ktor.client.plugins.contentnegotiation.*
import io.ktor.serialization.kotlinx.json.*
import mu.KotlinLogging
import net.cakeyfox.artistry.ArtistryClient
import net.cakeyfox.foxy.command.FoxyCommandManager
import net.cakeyfox.foxy.command.component.FoxyComponentManager
Expand All @@ -19,6 +20,7 @@ import net.cakeyfox.foxy.utils.FoxyUtils
import net.cakeyfox.foxy.utils.database.MongoDBClient
import net.dv8tion.jda.api.requests.GatewayIntent
import net.dv8tion.jda.api.utils.cache.CacheFlag
import kotlin.reflect.jvm.jvmName

class FoxyInstance(
val config: FoxyConfig
Expand All @@ -33,6 +35,7 @@ class FoxyInstance(
lateinit var httpClient: HttpClient

fun start() {
val logger = KotlinLogging.logger(this::class.jvmName)
mongoClient = MongoDBClient(this)
commandHandler = FoxyCommandManager(this)
utils = FoxyUtils(this)
Expand Down Expand Up @@ -71,5 +74,11 @@ class FoxyInstance(
jda.awaitReady()

ActivityUpdater(this)

Runtime.getRuntime().addShutdownHook(Thread {
logger.info { "Shutting down..." }
jda.awaitShutdown()
httpClient.close()
})
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,25 @@ import dev.minn.jda.ktx.coroutines.await
import dev.minn.jda.ktx.messages.InlineMessage
import dev.minn.jda.ktx.messages.MessageCreateBuilder
import dev.minn.jda.ktx.messages.MessageEditBuilder
import mu.KotlinLogging
import net.cakeyfox.foxy.FoxyInstance

import net.cakeyfox.foxy.utils.FoxyUtils
import net.cakeyfox.foxy.utils.locales.FoxyLocale
import net.cakeyfox.serializable.database.data.FoxyUser
import net.dv8tion.jda.api.entities.ISnowflake
import net.dv8tion.jda.api.entities.Message
import net.dv8tion.jda.api.events.interaction.GenericInteractionCreateEvent
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
import net.dv8tion.jda.api.events.interaction.component.ButtonInteractionEvent
import net.dv8tion.jda.api.events.interaction.component.StringSelectInteractionEvent
import net.dv8tion.jda.api.interactions.DiscordLocale
import net.dv8tion.jda.api.interactions.InteractionHook
import net.dv8tion.jda.api.interactions.commands.OptionType
import kotlin.reflect.jvm.jvmName

class FoxyInteractionContext(
val event: GenericInteractionCreateEvent, client: FoxyInstance
) {
private val logger = KotlinLogging.logger(this::class.jvmName)
val jda = event.jda
val foxy = client
val db = foxy.mongoClient
Expand All @@ -37,36 +39,48 @@ class FoxyInteractionContext(
return db.utils.user.getDiscordUser(user.id)
}

suspend fun reply(ephemeral: Boolean = false, block: InlineMessage<*>.() -> Unit): ISnowflake? {
suspend fun reply(ephemeral: Boolean = false, block: InlineMessage<*>.() -> Unit): Any? {
val msg = MessageCreateBuilder {
apply(block)
}

return when (event) {
is SlashCommandInteractionEvent -> {
if (event.isAcknowledged) {
event.hook.setEphemeral(ephemeral).sendMessage(msg.build()).await()
} else {
val defer = defer(ephemeral)

defer?.sendMessage(msg.build())?.await()
try {
if (event.isAcknowledged) {
event.hook.setEphemeral(ephemeral).sendMessage(msg.build()).await()
} else {
val defer = defer(ephemeral)

defer.sendMessage(msg.build()).queue()
}
} catch (e: Exception) {
logger.warn { "Failed to reply command! It was deleted? ${e.message}" }
}
}

is ButtonInteractionEvent -> {
if (event.isAcknowledged) {
event.hook.setEphemeral(ephemeral).sendMessage(msg.build()).await()
} else {
val defer = defer(ephemeral)
defer?.sendMessage(msg.build())?.await()
try {
if (event.isAcknowledged) {
event.hook.setEphemeral(ephemeral).sendMessage(msg.build()).await()
} else {
val defer = defer(ephemeral)
defer.sendMessage(msg.build()).queue()
}
} catch (e: Exception) {
logger.warn { "Failed to reply button! It was deleted? ${e.message}"}
}
}

is StringSelectInteractionEvent -> {
if (event.isAcknowledged) {
event.hook
} else {
event.deferReply().setEphemeral(ephemeral).await()
try {
if (event.isAcknowledged) {
event.hook
} else {
event.deferReply().setEphemeral(ephemeral).queue()
}
} catch (e: Exception) {
logger.warn { "Failed to reply string select! It was deleted? ${e.message}"}
}
}

Expand All @@ -91,46 +105,56 @@ class FoxyInteractionContext(
}
}

suspend fun edit(block: InlineMessage<*>.() -> Unit): Message? {
suspend fun edit(block: InlineMessage<*>.() -> Unit): Unit? {
val msg = MessageEditBuilder {
apply(block)
}

return when (event) {
is ButtonInteractionEvent -> {
if (event.isAcknowledged) {
event.hook.editOriginal(msg.build()).await()
event.hook.editOriginal(msg.build()).queue()
} else {
event.deferEdit().await()?.editOriginal(msg.build())?.await()
event.deferEdit().await()?.editOriginal(msg.build())?.queue()
}
}

is StringSelectInteractionEvent -> {
if (event.isAcknowledged) {
event.hook.editOriginal(msg.build()).await()
event.hook.editOriginal(msg.build()).queue()
} else {
event.deferEdit().await()?.editOriginal(msg.build())?.await()
event.deferEdit().await()?.editOriginal(msg.build())?.queue()
}
}

else -> throw IllegalStateException("Cannot edit this event type. ${event.javaClass}")
}
}

suspend fun defer(ephemeral: Boolean = false) = when (event) {
suspend fun defer(ephemeral: Boolean = false): InteractionHook = when (event) {
is SlashCommandInteractionEvent -> {
if (event.isAcknowledged) {
try {
if (event.isAcknowledged) {
event.hook
} else {
event.deferReply().setEphemeral(ephemeral).await()
}
} catch (e: Exception) {
logger.warn { "Failed to defer command! It was deleted? ${e.message}" }
event.hook
} else {
event.deferReply().setEphemeral(ephemeral).await()
}
}

is ButtonInteractionEvent -> {
if (event.isAcknowledged) {
try {
if (event.isAcknowledged) {
event.hook
} else {
event.deferReply().setEphemeral(ephemeral).await()
}
} catch (e: Exception) {
logger.warn { "Failed to defer button! It was deleted? ${e.message}"}
event.hook
} else {
event.deferReply().setEphemeral(ephemeral).await()
}
}

Expand Down

0 comments on commit 39a5f3b

Please sign in to comment.