
com.freya02.botcommands.internal.commands.autobuilder.Utils.kt Maven / Gradle / Ivy
package com.freya02.botcommands.internal.commands.autobuilder
import com.freya02.botcommands.api.commands.CommandPath
import com.freya02.botcommands.api.commands.annotations.Cooldown
import com.freya02.botcommands.api.commands.application.AbstractApplicationCommandManager
import com.freya02.botcommands.api.commands.application.ApplicationCommand
import com.freya02.botcommands.api.commands.application.CommandScope
import com.freya02.botcommands.api.commands.application.GuildApplicationCommandManager
import com.freya02.botcommands.api.commands.application.annotations.NSFW
import com.freya02.botcommands.api.commands.application.annotations.Test
import com.freya02.botcommands.api.commands.application.builder.ApplicationCommandBuilder
import com.freya02.botcommands.api.commands.builder.CommandBuilder
import com.freya02.botcommands.internal.BContextImpl
import com.freya02.botcommands.internal.commands.autobuilder.metadata.CommandFunctionMetadata
import com.freya02.botcommands.internal.throwInternal
import com.freya02.botcommands.internal.throwUser
import com.freya02.botcommands.internal.utils.AnnotationUtils
import com.freya02.botcommands.internal.utils.ReflectionUtils.shortSignature
import kotlin.reflect.KFunction
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.hasAnnotation
//This is used so commands can't prevent other commands from being registered when an exception happens
internal inline fun > Iterable.forEachWithDelayedExceptions(block: (T) -> Unit) {
var ex: Throwable? = null
forEach { metadata ->
runCatching {
block(metadata)
}.onFailure {
when (ex) {
null -> ex = it.addFunction(metadata)
else -> ex!!.addSuppressed(it.addFunction(metadata))
}
}
}
if (ex != null) {
throw RuntimeException("Exception(s) occurred while registering annotated commands", ex)
}
}
@Suppress("NOTHING_TO_INLINE")
private inline fun > Throwable.addFunction(metadata: T) =
RuntimeException("An exception occurred while processing function ${metadata.func.shortSignature}", this)
internal fun checkCommandId(manager: AbstractApplicationCommandManager, instance: ApplicationCommand, commandId: String, path: CommandPath): Boolean {
if (manager is GuildApplicationCommandManager) {
val guildIds = instance.getGuildsForCommandId(commandId, path) ?: return true
if (manager.guild.idLong !in guildIds) {
return false //Don't push command if it isn't allowed
}
}
return true
}
internal fun checkTestCommand(manager: AbstractApplicationCommandManager, func: KFunction<*>, scope: CommandScope, context: BContextImpl): Boolean {
if (func.hasAnnotation()) {
if (scope != CommandScope.GUILD) throwUser(func, "Test commands must have their scope set to GUILD")
if (manager !is GuildApplicationCommandManager) throwInternal("GUILD scoped command was not registered with a guild command manager")
//Returns whether the command can be registered
return manager.guild.idLong in AnnotationUtils.getEffectiveTestGuildIds(context, func)
}
return true
}
internal fun CommandBuilder.fillCommandBuilder(func: KFunction<*>) {
func.findAnnotation()?.let { cooldownAnnotation ->
cooldown {
scope = cooldownAnnotation.cooldownScope
cooldown = cooldownAnnotation.cooldown
unit = cooldownAnnotation.unit
}
}
userPermissions = AnnotationUtils.getUserPermissions(func)
botPermissions = AnnotationUtils.getBotPermissions(func)
}
@Suppress("UNCHECKED_CAST")
fun KFunction<*>.castFunction() = this as KFunction
internal fun ApplicationCommandBuilder<*>.fillApplicationCommandBuilder(func: KFunction<*>, annotation: Annotation) {
if (func.hasAnnotation()) {
throwUser(func, "@${NSFW::class.simpleName} can only be used on text commands, use the #nsfw method on your annotation instead")
}
nsfw = AnnotationUtils.getAnnotationValue(annotation, "nsfw")
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy