From 3dd19cc568f6ac7e77bfdc7851f34355f53ef603 Mon Sep 17 00:00:00 2001 From: Hope <34831095+HopeBaron@users.noreply.github.com> Date: Fri, 30 Jul 2021 13:47:54 +0300 Subject: [PATCH] support type 10 number arguement for slash commands (#351) --- CHANGELOG.md | 10 ++++++ common/src/main/kotlin/entity/Interactions.kt | 23 +++++++++++++- core/api/core.api | 3 +- .../interaction/ComponentInteraction.kt | 7 +++-- .../kotlin/entity/interaction/Interaction.kt | 31 ++++++++++++------- .../interaction/ApplicationCommandBuilders.kt | 7 +++++ .../builder/interaction/OptionsBuilder.kt | 11 +++++++ 7 files changed, 77 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ece57b24d084..62667c103f49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,13 @@ +# 0.7.4 + +## Changes + +* Promote user property in component interaction to a data object. + +## Fixes + +* Fixed `ComponentInteraction#user` throwing a `NullPointerException` when the interaction was created in a direct message. + # 0.7.3 ## Additions diff --git a/common/src/main/kotlin/entity/Interactions.kt b/common/src/main/kotlin/entity/Interactions.kt index 3ef59142d86b..3f96b7ff5ec8 100644 --- a/common/src/main/kotlin/entity/Interactions.kt +++ b/common/src/main/kotlin/entity/Interactions.kt @@ -72,6 +72,7 @@ sealed class ApplicationCommandOptionType(val type: Int) { object Channel : ApplicationCommandOptionType(7) object Role : ApplicationCommandOptionType(8) object Mentionable : ApplicationCommandOptionType(9) + object Number : ApplicationCommandOptionType(10) class Unknown(type: Int) : ApplicationCommandOptionType(type) companion object; @@ -92,6 +93,7 @@ sealed class ApplicationCommandOptionType(val type: Int) { 7 -> Channel 8 -> Role 9 -> Mentionable + 10 -> Number else -> Unknown(type) } } @@ -111,6 +113,7 @@ sealed class Choice { abstract val value: T class IntChoice(override val name: String, override val value: Int) : Choice() + class NumberChoice(override val name: String, override val value: Double) : Choice() class StringChoice(override val name: String, override val value: String) : Choice() internal class ChoiceSerializer(serializer: KSerializer) : KSerializer> { override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Choice") { @@ -133,7 +136,11 @@ sealed class Choice { } endStructure(descriptor) } - return if (value.isString) StringChoice(name, value.toString()) else IntChoice(name, value.int) + return when { + value.intOrNull != null -> IntChoice(name, value.int) + value.doubleOrNull != null -> NumberChoice(name, value.double) + else -> StringChoice(name, value.toString()) + } } override fun serialize(encoder: Encoder, value: Choice<*>) { @@ -400,6 +407,16 @@ sealed class CommandArgument : Option() { override fun toString(): String = "IntegerArgument(name=$name, value=$value)" } + class NumberArgument( + override val name: String, + override val value: Double + ) : CommandArgument() { + override val type: ApplicationCommandOptionType + get() = ApplicationCommandOptionType.Number + + override fun toString(): String = "NumberArgument(name=$name, value=$value)" + } + class BooleanArgument( override val name: String, override val value: Boolean @@ -509,6 +526,10 @@ sealed class CommandArgument : Option() { ApplicationCommandOptionType.Integer -> IntegerArgument( name, json.decodeFromJsonElement(Int.serializer(), element) ) + + ApplicationCommandOptionType.Number -> NumberArgument( + name, json.decodeFromJsonElement(Double.serializer(), element) + ) ApplicationCommandOptionType.Channel -> ChannelArgument( name, json.decodeFromJsonElement(Snowflake.serializer(), element) ) diff --git a/core/api/core.api b/core/api/core.api index f6c4968d527a..6295810ef6d0 100644 --- a/core/api/core.api +++ b/core/api/core.api @@ -5735,7 +5735,8 @@ public abstract class dev/kord/core/entity/interaction/ComponentInteraction : de public abstract fun getComponent ()Ldev/kord/core/entity/component/Component; public final fun getComponentId ()Ljava/lang/String; public final fun getMessage ()Ldev/kord/core/entity/Message; - public fun getUser ()Ldev/kord/core/behavior/UserBehavior; + public synthetic fun getUser ()Ldev/kord/core/behavior/UserBehavior; + public fun getUser ()Ldev/kord/core/entity/User; public fun hashCode ()I public abstract fun toString ()Ljava/lang/String; public abstract fun withStrategy (Ldev/kord/core/supplier/EntitySupplyStrategy;)Ldev/kord/core/entity/interaction/ComponentInteraction; diff --git a/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt b/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt index b90cc839fbd6..4ee5eec4e9c0 100644 --- a/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt +++ b/core/src/main/kotlin/entity/interaction/ComponentInteraction.kt @@ -3,6 +3,7 @@ package dev.kord.core.entity.interaction import dev.kord.common.annotation.KordPreview import dev.kord.common.entity.ComponentType import dev.kord.common.entity.Snowflake +import dev.kord.common.entity.optional.map import dev.kord.common.entity.optional.orEmpty import dev.kord.common.entity.optional.unwrap import dev.kord.core.Kord @@ -10,6 +11,7 @@ import dev.kord.core.behavior.UserBehavior import dev.kord.core.behavior.interaction.ComponentInteractionBehavior import dev.kord.core.cache.data.InteractionData import dev.kord.core.entity.Message +import dev.kord.core.entity.User import dev.kord.core.entity.component.ActionRowComponent import dev.kord.core.entity.component.ButtonComponent import dev.kord.core.entity.component.Component @@ -27,8 +29,9 @@ import dev.kord.rest.builder.component.SelectMenuBuilder @KordPreview sealed class ComponentInteraction : Interaction(), ComponentInteractionBehavior { - override val user: UserBehavior - get() = UserBehavior(data.member.value!!.userId, kord) + override val user: User + get() = User(data.user.value!!, kord) + /** * The message that contains the interacted component, null if the message is ephemeral. diff --git a/core/src/main/kotlin/entity/interaction/Interaction.kt b/core/src/main/kotlin/entity/interaction/Interaction.kt index 6e4b7eeb8b67..989fd458616e 100644 --- a/core/src/main/kotlin/entity/interaction/Interaction.kt +++ b/core/src/main/kotlin/entity/interaction/Interaction.kt @@ -13,17 +13,16 @@ import dev.kord.core.behavior.GuildInteractionBehavior import dev.kord.core.behavior.MemberBehavior import dev.kord.core.behavior.UserBehavior import dev.kord.core.behavior.channel.GuildMessageChannelBehavior -import dev.kord.core.behavior.interaction.ComponentInteractionBehavior import dev.kord.core.behavior.interaction.InteractionBehavior import dev.kord.core.cache.data.ApplicationInteractionData import dev.kord.core.cache.data.InteractionData import dev.kord.core.cache.data.ResolvedObjectsData -import dev.kord.core.entity.* +import dev.kord.core.entity.Entity +import dev.kord.core.entity.Member +import dev.kord.core.entity.Role +import dev.kord.core.entity.User import dev.kord.core.entity.channel.DmChannel import dev.kord.core.entity.channel.ResolvedChannel -import dev.kord.core.entity.component.ActionRowComponent -import dev.kord.core.entity.component.ButtonComponent -import dev.kord.core.entity.component.Component import dev.kord.core.supplier.EntitySupplier import dev.kord.core.supplier.EntitySupplyStrategy @@ -275,6 +274,11 @@ sealed class OptionValue(val value: T) { override fun toString(): String = "IntOptionValue(value=$value)" } + + class NumberOptionValue(value: Double) : OptionValue(value) { + override fun toString(): String = "DoubleOptionValue(value=$value)" + } + class StringOptionValue(value: String) : OptionValue(value) { override fun toString(): String = "StringOptionValue(value=$value)" } @@ -291,6 +295,7 @@ sealed class OptionValue(val value: T) { @KordPreview fun OptionValue(value: CommandArgument<*>, resolvedObjects: ResolvedObjects?): OptionValue<*> { return when (value) { + is CommandArgument.NumberArgument -> OptionValue.NumberOptionValue(value.value) is CommandArgument.BooleanArgument -> OptionValue.BooleanOptionValue(value.value) is CommandArgument.IntegerArgument -> OptionValue.IntOptionValue(value.value) is CommandArgument.StringArgument -> OptionValue.StringOptionValue(value.value) @@ -307,7 +312,7 @@ fun OptionValue(value: CommandArgument<*>, resolvedObjects: ResolvedObjects?): O val member = resolvedObjects?.members.orEmpty()[value.value] val role = resolvedObjects?.roles.orEmpty()[value.value] - OptionValue.MentionableOptionValue((channel ?: member ?: user ?: role)!!) + OptionValue.MentionableOptionValue((channel ?: member ?: user ?: role)!!) } is CommandArgument.RoleArgument -> { @@ -374,11 +379,12 @@ class GuildInteraction( /** * The invoker of the command as [MemberBehavior]. */ - val member: Member get() = Member( - data.member.value!!, - data.user.value!!, - kord - ) + val member: Member + get() = Member( + data.member.value!!, + data.user.value!!, + kord + ) override val channel: GuildMessageChannelBehavior get() = GuildMessageChannelBehavior(guildId, channelId, kord) @@ -412,6 +418,9 @@ fun OptionValue<*>.boolean() = value as Boolean @KordPreview fun OptionValue<*>.int() = value as Int +@KordPreview +fun OptionValue<*>.number() = value as Double + @KordPreview fun OptionValue<*>.mentionable(): Entity { return value as Entity diff --git a/rest/src/main/kotlin/builder/interaction/ApplicationCommandBuilders.kt b/rest/src/main/kotlin/builder/interaction/ApplicationCommandBuilders.kt index 4764981f7597..a5a1aee78a46 100644 --- a/rest/src/main/kotlin/builder/interaction/ApplicationCommandBuilders.kt +++ b/rest/src/main/kotlin/builder/interaction/ApplicationCommandBuilders.kt @@ -47,6 +47,13 @@ sealed class BaseApplicationBuilder { options!!.add(StringChoiceBuilder(name, description).apply(builder)) } + @OptIn(ExperimentalContracts::class) + inline fun number(name: String, description: String, builder: NumberChoiceBuilder.() -> Unit = {}) { + contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } + if (options == null) options = mutableListOf() + options!!.add(NumberChoiceBuilder(name, description).apply(builder)) + } + @OptIn(ExperimentalContracts::class) inline fun group(name: String, description: String, builder: GroupCommandBuilder.() -> Unit) { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } diff --git a/rest/src/main/kotlin/builder/interaction/OptionsBuilder.kt b/rest/src/main/kotlin/builder/interaction/OptionsBuilder.kt index 3991bd16cc69..7b22adfca5ff 100644 --- a/rest/src/main/kotlin/builder/interaction/OptionsBuilder.kt +++ b/rest/src/main/kotlin/builder/interaction/OptionsBuilder.kt @@ -71,6 +71,17 @@ class IntChoiceBuilder(name: String, description: String) : } } +@KordPreview +@KordDsl +class NumberChoiceBuilder(name: String, description: String) : + BaseChoiceBuilder(name, description, ApplicationCommandOptionType.Number) { + override fun choice(name: String, value: Double) { + if (choices == null) choices = mutableListOf() + choices!!.add(Choice.NumberChoice(name, value)) + } + +} + @KordDsl @KordPreview class StringChoiceBuilder(name: String, description: String) :