From 48c1722668c76e74cd9d0e243982f74722c8817b Mon Sep 17 00:00:00 2001 From: freya02 <41875020+freya022@users.noreply.github.com> Date: Fri, 30 May 2025 16:39:52 +0200 Subject: [PATCH 1/2] Set an empty list for vararg arguments with no values available --- .../botcommands/internal/utils/ExecutionUtils.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt b/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt index 90924e91f..ed6fbd741 100644 --- a/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt +++ b/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt @@ -7,6 +7,7 @@ import io.github.freya022.botcommands.internal.parameters.AggregatedParameterMix import io.github.freya022.botcommands.internal.parameters.MethodParameterMixin import io.github.freya022.botcommands.internal.utils.ReflectionUtils.function import kotlin.reflect.KParameter +import kotlin.reflect.full.valueParameters internal enum class InsertOptionResult { OK, @@ -68,12 +69,21 @@ private suspend fun insertAggregate(firstParam: Any, aggregatedObjects: MutableM } } else { val aggregatorArguments: MutableMap = HashMap(aggregator.parametersSize) + var addedOption = false for (option in parameter.options) { //This is necessary to distinguish between null mappings and default mappings if (option in optionValues) { aggregatorArguments[option] = optionValues[option] + addedOption = true } } + // If this is not a vararg, it should throw later when calling the aggregator + if (!addedOption && parameter.isVararg) { + // TODO: this may cause issues with text commands + // for example when a variation has no argument + // and another variation has a 0-N vararg + aggregatorArguments[parameter.aggregator.kFunction.valueParameters.last()] = emptyList() + } for (nestedAggregatedParameter in parameter.nestedAggregatedParameters) { insertAggregate(firstParam, aggregatorArguments, optionValues, nestedAggregatedParameter) From 5dcc3d97de14bd2ab75a65a1cf7b6a239681ffa6 Mon Sep 17 00:00:00 2001 From: freya02 <41875020+freya022@users.noreply.github.com> Date: Fri, 13 Jun 2025 20:33:37 +0200 Subject: [PATCH 2/2] Require at least 1 required option for text command varargs Required so there is no confusion between, for example: - - Added checks for slash commands too --- .../botcommands/api/commands/annotations/VarArgs.kt | 7 ++++++- .../application/slash/builder/SlashCommandBuilderImpl.kt | 3 +++ .../builder/SlashCommandOptionAggregateBuilderImpl.kt | 3 +++ .../text/builder/TextCommandVariationBuilderImpl.kt | 4 +++- .../builder/TextCommandOptionAggregateBuilderImpl.kt | 2 ++ .../freya022/botcommands/internal/utils/ExecutionUtils.kt | 3 --- 6 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/io/github/freya022/botcommands/api/commands/annotations/VarArgs.kt b/src/main/kotlin/io/github/freya022/botcommands/api/commands/annotations/VarArgs.kt index 744607c1a..26411b221 100644 --- a/src/main/kotlin/io/github/freya022/botcommands/api/commands/annotations/VarArgs.kt +++ b/src/main/kotlin/io/github/freya022/botcommands/api/commands/annotations/VarArgs.kt @@ -7,6 +7,7 @@ import io.github.freya022.botcommands.api.commands.application.slash.options.bui import io.github.freya022.botcommands.api.commands.text.annotations.TextOption import io.github.freya022.botcommands.api.commands.text.builder.TextCommandVariationBuilder import io.github.freya022.botcommands.api.commands.text.options.builder.inlineClassOptionVararg +import net.dv8tion.jda.api.interactions.commands.build.CommandData /** * Generates N command options from the specified [@SlashOption][SlashOption] or [@TextOption][TextOption]. @@ -32,12 +33,16 @@ import io.github.freya022.botcommands.api.commands.text.options.builder.inlineCl @Retention(AnnotationRetention.RUNTIME) annotation class VarArgs( /** - * The number of times this option needs to appear, which must be between 1 and {@value CommandData#MAX_OPTIONS}. + * The number of times this option needs to appear, must be positive. */ val value: Int, /** * The number of required options for this vararg. + * + * For slash commands, this must can be 0, positive, or how many remaining options there are until [MAX_OPTIONS][CommandData.MAX_OPTIONS]. + * + * For text commands, this must be at least 1. */ val numRequired: Int = 1 ) diff --git a/src/main/kotlin/io/github/freya022/botcommands/internal/commands/application/slash/builder/SlashCommandBuilderImpl.kt b/src/main/kotlin/io/github/freya022/botcommands/internal/commands/application/slash/builder/SlashCommandBuilderImpl.kt index 92b67e84a..89909c5ef 100644 --- a/src/main/kotlin/io/github/freya022/botcommands/internal/commands/application/slash/builder/SlashCommandBuilderImpl.kt +++ b/src/main/kotlin/io/github/freya022/botcommands/internal/commands/application/slash/builder/SlashCommandBuilderImpl.kt @@ -44,6 +44,9 @@ internal abstract class SlashCommandBuilderImpl internal constructor( } final override fun optionVararg(declaredName: String, amount: Int, requiredAmount: Int, optionNameSupplier: (Int) -> String, block: SlashCommandOptionBuilder.(Int) -> Unit) { + require(amount > 0) { "Amount must be positive" } + require(requiredAmount >= 0) { "Required amount must be zero or positive" } + //Same as in TextCommandVariationBuilder#optionVararg varargAggregate(declaredName) { for (i in 0.. String, block: SlashCommandOptionBuilder.(Int) -> Unit) { + require(amount > 0) { "Amount must be positive" } + require(requiredAmount >= 0) { "Required amount must be zero or positive" } + //Same as in TextCommandVariationBuilder#optionVararg varargAggregate(declaredName) { for (i in 0.. String, block: TextCommandOptionBuilder.(Int) -> Unit) { - if (aggregateContainer.hasVararg()) + if (hasVararg()) throwArgument("Cannot have more than 1 vararg in text commands") + require(amount > 0) { "Amount must be positive" } + require(requiredAmount > 0) { "Required amount must be positive" } //Same as in SlashCommandBuilder#optionVararg aggregateContainer.varargAggregate(declaredName) { diff --git a/src/main/kotlin/io/github/freya022/botcommands/internal/commands/text/options/builder/TextCommandOptionAggregateBuilderImpl.kt b/src/main/kotlin/io/github/freya022/botcommands/internal/commands/text/options/builder/TextCommandOptionAggregateBuilderImpl.kt index a4c907933..9cbea35bd 100644 --- a/src/main/kotlin/io/github/freya022/botcommands/internal/commands/text/options/builder/TextCommandOptionAggregateBuilderImpl.kt +++ b/src/main/kotlin/io/github/freya022/botcommands/internal/commands/text/options/builder/TextCommandOptionAggregateBuilderImpl.kt @@ -35,6 +35,8 @@ internal class TextCommandOptionAggregateBuilderImpl internal constructor( override fun optionVararg(declaredName: String, amount: Int, requiredAmount: Int, optionNameSupplier: (Int) -> String, block: TextCommandOptionBuilder.(Int) -> Unit) { if (hasVararg()) throwArgument("Cannot have more than 1 vararg in text commands") + require(amount > 0) { "Amount must be positive" } + require(requiredAmount > 0) { "Required amount must be positive" } //Same as in TextCommandVariationBuilder#optionVararg varargAggregate(declaredName) { diff --git a/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt b/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt index ed6fbd741..465552b92 100644 --- a/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt +++ b/src/main/kotlin/io/github/freya022/botcommands/internal/utils/ExecutionUtils.kt @@ -79,9 +79,6 @@ private suspend fun insertAggregate(firstParam: Any, aggregatedObjects: MutableM } // If this is not a vararg, it should throw later when calling the aggregator if (!addedOption && parameter.isVararg) { - // TODO: this may cause issues with text commands - // for example when a variation has no argument - // and another variation has a 0-N vararg aggregatorArguments[parameter.aggregator.kFunction.valueParameters.last()] = emptyList() }