Skip to content

Commit

Permalink
Merge pull request #200 from discord-diabetes/feat/coroutines
Browse files Browse the repository at this point in the history
  • Loading branch information
cascer1 authored Oct 30, 2023
2 parents 050db02 + 7164f52 commit 51095cc
Show file tree
Hide file tree
Showing 11 changed files with 154 additions and 140 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,11 @@ import net.dv8tion.jda.api.interactions.components.buttons.Button
interface ApplicationCommand {
val commandName: String

fun execute(event: SlashCommandInteractionEvent)
suspend fun execute(event: SlashCommandInteractionEvent)

fun execute(event: ButtonInteractionEvent): Boolean = false
suspend fun execute(event: ButtonInteractionEvent): Boolean = false

fun execute(event: ModalInteractionEvent): Boolean = false
suspend fun execute(event: ModalInteractionEvent): Boolean = false

fun config(): CommandData

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.dongtronic.diabot.platforms.discord.commands

import com.jagrosh.jdautilities.command.Command
import com.jagrosh.jdautilities.command.CommandEvent
import dev.minn.jda.ktx.events.CoroutineEventManager
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

abstract class DiscordCommand(category: Category, parent: Command?) : Command() {
var examples = arrayOfNulls<String>(0)
Expand All @@ -13,6 +17,25 @@ abstract class DiscordCommand(category: Category, parent: Command?) : Command()
this.parent = parent
}

override fun execute(event: CommandEvent) {
// The `.injectKTX()` line in the main class changes the event manager to a CoroutineEventManager
val manager = event.jda.eventManager as? CoroutineEventManager
if (manager == null) {
// fallback to blocking if the event manager isn't a CoroutineEventManager for some reason
runBlocking {
launch {
executeSuspend(event)
}
}
} else {
manager.launch {
executeSuspend(event)
}
}
}

open suspend fun executeSuspend(event: CommandEvent) {}

override fun toString(): String {
return if (this.parent != null) {
"${this.parent} $name"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class SampleSubCommand(category: Category, parent: Command?) : DiscordCommand(ca
this.aliases = arrayOf("l")
}

override fun execute(event: CommandEvent?) {
override fun execute(event: CommandEvent) {
// do a thing
}
}
Expand All @@ -53,7 +53,7 @@ class SampleSubCommand(category: Category, parent: Command?) : DiscordCommand(ca
this.aliases = arrayOf("a")
}

override fun execute(event: CommandEvent?) {
override fun execute(event: CommandEvent) {
// do another thing
}
}
Expand All @@ -68,7 +68,7 @@ class SampleSubCommand(category: Category, parent: Command?) : DiscordCommand(ca
this.aliases = arrayOf("remove", "d", "r")
}

override fun execute(event: CommandEvent?) {
override fun execute(event: CommandEvent) {
// do the third thing
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class ConversionApplicationCommand : ApplicationCommand {
)
}

override fun execute(event: SlashCommandInteractionEvent) {
override suspend fun execute(event: SlashCommandInteractionEvent) {
val glucoseNumber = event.getOption(commandArgGlucose)!!.asString
val glucoseUnit = event.getOption(commandArgUnit)?.asString

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class EstimationApplicationCommand : ApplicationCommand {
)
}

override fun execute(event: SlashCommandInteractionEvent) {
override suspend fun execute(event: SlashCommandInteractionEvent) {
when (event.subcommandName) {
commandModeAverage -> estimateAverage(event)
commandModeA1c -> estimateA1c(event)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AwyissApplicationCommand : ApplicationCommand {
.addOption(OptionType.BOOLEAN, commandArgSfw, "Safe for work", false)
}

override fun execute(event: SlashCommandInteractionEvent) {
override suspend fun execute(event: SlashCommandInteractionEvent) {
val stringValue = event.getOption(commandArgValue)!!.asString
val sfwValue = event.getOption(commandArgSfw)?.asBoolean ?: true

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ class NightscoutApplicationCommand : ApplicationCommand {
private val commandButtonDeleteConfirm = "nsdeleteyes".generateId()
private val commandButtonDeleteCancel = "nsdeleteno".generateId()

override fun execute(event: SlashCommandInteractionEvent) {
override suspend fun execute(event: SlashCommandInteractionEvent) {
when (event.subcommandGroup) {
groupNameSet -> when (event.subcommandName) {
commandModeToken -> setToken(event)
Expand All @@ -70,7 +70,7 @@ class NightscoutApplicationCommand : ApplicationCommand {
}
}

override fun execute(event: ButtonInteractionEvent): Boolean {
override suspend fun execute(event: ButtonInteractionEvent): Boolean {
when (event.componentId) {
commandButtonDeleteConfirm -> deleteData(event)
commandButtonDeleteCancel -> cancelDeleteData(event)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import com.dongtronic.nightscout.data.NightscoutDTO
import com.dongtronic.nightscout.exceptions.NoNightscoutDataException
import com.fasterxml.jackson.core.JsonProcessingException
import dev.minn.jda.ktx.coroutines.await
import kotlinx.coroutines.launch
import kotlinx.coroutines.reactor.awaitSingle
import kotlinx.coroutines.runBlocking
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent
import net.dv8tion.jda.api.interactions.commands.OptionType
import net.dv8tion.jda.api.interactions.commands.build.CommandData
Expand All @@ -37,7 +35,7 @@ class NightscoutGraphApplicationCommand : ApplicationCommand {
private val logger = logger()
private val cooldowns = mutableMapOf<String, Long>()

override fun execute(event: SlashCommandInteractionEvent) {
override suspend fun execute(event: SlashCommandInteractionEvent) {
val cooldownSeconds = getCooldown(event.user.id)
if (cooldownSeconds != null) {
val plural = if (abs(cooldownSeconds) != 1L) "s" else ""
Expand All @@ -56,31 +54,27 @@ class NightscoutGraphApplicationCommand : ApplicationCommand {
return
}

runBlocking {
launch {
try {
val enabled = !event.isFromGuild ||
GraphDisableDAO.instance.getGraphEnabled(event.guild!!.id).awaitSingle()
try {
val enabled = !event.isFromGuild ||
GraphDisableDAO.instance.getGraphEnabled(event.guild!!.id).awaitSingle()

if (!enabled) {
event.reply("Nightscout graphs are disabled in this guild").setEphemeral(true).queue()
return@launch
}
if (!enabled) {
event.reply("Nightscout graphs are disabled in this guild").setEphemeral(true).queue()
return
}

event.deferReply(false).queue()

val chart = getDataSet(event.user.id, hours).awaitSingle()
val imageBytes = chart.getBitmapBytes(BitmapFormat.PNG)
event.hook.editOriginalAttachments(FileUpload.fromData(imageBytes, "graph.png")).submit().await()
applyCooldown(event.user.id)
} catch (e: Exception) {
logger.error("Error generating NS graph for ${event.user}")
if (e is NightscoutFetchException) {
event.hook.editOriginal(NightscoutCommand.handleGrabError(e.originalException, event.user, e.userDTO)).queue()
} else {
event.hook.editOriginal(NightscoutCommand.handleError(e)).queue()
}
}
event.deferReply(false).queue()

val chart = getDataSet(event.user.id, hours).awaitSingle()
val imageBytes = chart.getBitmapBytes(BitmapFormat.PNG)
event.hook.editOriginalAttachments(FileUpload.fromData(imageBytes, "graph.png")).submit().await()
applyCooldown(event.user.id)
} catch (e: Exception) {
logger.error("Error generating NS graph for ${event.user}")
if (e is NightscoutFetchException) {
event.hook.editOriginal(NightscoutCommand.handleGrabError(e.originalException, event.user, e.userDTO)).queue()
} else {
event.hook.editOriginal(NightscoutCommand.handleError(e)).queue()
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import com.dongtronic.diabot.platforms.discord.commands.DiscordCommand
import com.dongtronic.diabot.util.logger
import com.jagrosh.jdautilities.command.CommandEvent
import dev.minn.jda.ktx.coroutines.await
import kotlinx.coroutines.launch
import kotlinx.coroutines.reactor.awaitSingle
import kotlinx.coroutines.runBlocking
import net.dv8tion.jda.api.utils.messages.MessageCreateBuilder
import net.dv8tion.jda.api.utils.messages.MessageCreateData

Expand All @@ -25,54 +23,50 @@ class QuoteAddCommand(category: Category, parent: QuoteCommand) : DiscordCommand
this.examples = arrayOf(this.parent!!.name + " add \"this is a quote added manually\" - gar")
}

override fun execute(event: CommandEvent) {
runBlocking {
launch {
if (!QuoteDAO.awaitCheckRestrictions(event.guildChannel, warnDisabledGuild = true)) return@launch
override suspend fun executeSuspend(event: CommandEvent) {
if (!QuoteDAO.awaitCheckRestrictions(event.guildChannel, warnDisabledGuild = true)) return

val match = quoteRegex.find(event.message.contentRaw)
if (match == null) {
event.replyError("Could not parse quote. Please make sure you are using the correct format for this command")
return@launch
}

val message = match.groups["message"]!!.value.trim()
var author = match.groups["author"]!!.value.trim()
var authorId = 0L

val mention = mentionsRegex.matchEntire(author)
if (mention != null) {
val uid = mention.groups["uid"]!!.value.trim().toLongOrNull()
val match = quoteRegex.find(event.message.contentRaw)
if (match == null) {
event.replyError("Could not parse quote. Please make sure you are using the correct format for this command")
return
}

if (uid != null) {
try {
val user = event.jda.retrieveUserById(uid).await()
author = user.name
authorId = uid
} catch (ignored: Throwable) {
}
}
}
val message = match.groups["message"]!!.value.trim()
var author = match.groups["author"]!!.value.trim()
var authorId = 0L

val quoteDto = QuoteDTO(
guildId = event.guild.id,
channelId = event.channel.id,
author = author,
authorId = authorId.toString(),
quoterId = event.author.id,
message = message,
messageId = event.message.id
)
val mention = mentionsRegex.matchEntire(author)
if (mention != null) {
val uid = mention.groups["uid"]!!.value.trim().toLongOrNull()

if (uid != null) {
try {
val quote = QuoteDAO.getInstance().addQuote(quoteDto).awaitSingle()
event.reply(createAddedMessage(event.member.asMention, quote.quoteId!!))
} catch (e: Throwable) {
event.replyError("Could not add quote: ${e.message}")
logger.warn("Unexpected error: " + e::class.simpleName + " - " + e.message)
val user = event.jda.retrieveUserById(uid).await()
author = user.name
authorId = uid
} catch (ignored: Throwable) {
}
}
}

val quoteDto = QuoteDTO(
guildId = event.guild.id,
channelId = event.channel.id,
author = author,
authorId = authorId.toString(),
quoterId = event.author.id,
message = message,
messageId = event.message.id
)

try {
val quote = QuoteDAO.getInstance().addQuote(quoteDto).awaitSingle()
event.reply(createAddedMessage(event.member.asMention, quote.quoteId!!))
} catch (e: Throwable) {
event.replyError("Could not add quote: ${e.message}")
logger.warn("Unexpected error: " + e::class.simpleName + " - " + e.message)
}
}

companion object {
Expand Down
Loading

0 comments on commit 51095cc

Please sign in to comment.