
com.freya02.botcommands.internal.modals.ModalHandlerInfo.kt Maven / Gradle / Ivy
package com.freya02.botcommands.internal.modals
import com.freya02.botcommands.api.commands.builder.CustomOptionBuilder
import com.freya02.botcommands.api.modals.annotations.ModalHandler
import com.freya02.botcommands.api.modals.annotations.ModalInput
import com.freya02.botcommands.internal.*
import com.freya02.botcommands.internal.core.options.Option
import com.freya02.botcommands.internal.core.options.OptionType
import com.freya02.botcommands.internal.core.reflection.*
import com.freya02.botcommands.internal.parameters.CustomMethodOption
import com.freya02.botcommands.internal.parameters.OptionParameter
import com.freya02.botcommands.internal.utils.InsertOptionResult
import com.freya02.botcommands.internal.utils.ReflectionUtils.nonInstanceParameters
import com.freya02.botcommands.internal.utils.mapFinalParameters
import com.freya02.botcommands.internal.utils.mapOptions
import com.freya02.botcommands.internal.utils.tryInsertNullableOption
import net.dv8tion.jda.api.events.interaction.ModalInteractionEvent
import kotlin.collections.component1
import kotlin.collections.component2
import kotlin.collections.set
import kotlin.reflect.full.*
import kotlin.reflect.jvm.jvmErasure
import com.freya02.botcommands.api.modals.annotations.ModalData as ModalDataAnnotation
class ModalHandlerInfo(
val context: BContextImpl,
override val eventFunction: MemberEventFunction
) : IExecutableInteractionInfo {
override val parameters: List
private val expectedModalDatas: Int
private val expectedModalInputs: Int
val handlerName: String
init {
val annotation = function.findAnnotation()!!
handlerName = annotation.name
parameters = function.nonInstanceParameters.drop(1).transformParameters(
builderBlock = { function, parameter, declaredName ->
when {
parameter.hasAnnotation() -> ModalHandlerInputOptionBuilder(OptionParameter.fromSelfAggregate(function, declaredName))
parameter.hasAnnotation() -> ModalHandlerDataOptionBuilder(OptionParameter.fromSelfAggregate(function, declaredName))
else -> CustomOptionBuilder(OptionParameter.fromSelfAggregate(function, declaredName))
}
},
aggregateBlock = { ModalHandlerParameter(context, it) }
)
val options = parameters.flatMap { it.allOptions }
expectedModalDatas = options.filterIsInstance().count()
expectedModalInputs = options.filterIsInstance().count()
}
@Throws(Exception::class)
suspend fun execute(modalData: ModalData, event: ModalInteractionEvent): Boolean {
val handlerData = modalData.handlerData as? PersistentModalHandlerData ?: throwInternal("This method should have not been ran as there is no handler data")
val inputDataMap = modalData.inputDataMap
val inputNameToInputIdMap: MutableMap = HashMap()
inputDataMap.forEach { (inputId: String, inputData: InputData) ->
inputNameToInputIdMap[inputData.inputName] = inputId
}
val userDatas = handlerData.userData
//Check if there's enough arguments to fit user data + modal inputs
requireUser(expectedModalDatas == userDatas.size && expectedModalInputs == event.values.size, function) {
"""
Modal handler does not match the received modal data:
Method signature: $expectedModalDatas userdata parameters and $expectedModalInputs modal input(s)
Discord data: ${userDatas.size} userdata parameters and ${event.values.size} modal input(s)""".trimIndent()
}
val userDataIterator = userDatas.iterator()
val optionValues = parameters.mapOptions { option ->
if (tryInsertOption(event, option, inputNameToInputIdMap, userDataIterator, this) == InsertOptionResult.ABORT)
throwInternal(::tryInsertOption, "Insertion function shouldn't have been aborted")
}
function.callSuspendBy(parameters.mapFinalParameters(event, optionValues))
return true
}
private suspend fun tryInsertOption(
event: ModalInteractionEvent,
option: Option,
inputNameToInputIdMap: Map,
userDataIterator: Iterator,
optionMap: MutableMap
© 2015 - 2025 Weber Informatics LLC | Privacy Policy