Skip to content

Commit

Permalink
support type 10 number arguement for slash commands (#351)
Browse files Browse the repository at this point in the history
  • Loading branch information
HopeBaron authored Jul 30, 2021
1 parent afe8505 commit 3dd19cc
Show file tree
Hide file tree
Showing 7 changed files with 77 additions and 15 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
23 changes: 22 additions & 1 deletion common/src/main/kotlin/entity/Interactions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -92,6 +93,7 @@ sealed class ApplicationCommandOptionType(val type: Int) {
7 -> Channel
8 -> Role
9 -> Mentionable
10 -> Number
else -> Unknown(type)
}
}
Expand All @@ -111,6 +113,7 @@ sealed class Choice<out T> {
abstract val value: T

class IntChoice(override val name: String, override val value: Int) : Choice<Int>()
class NumberChoice(override val name: String, override val value: Double) : Choice<Double>()
class StringChoice(override val name: String, override val value: String) : Choice<String>()
internal class ChoiceSerializer<T>(serializer: KSerializer<T>) : KSerializer<Choice<*>> {
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Choice") {
Expand All @@ -133,7 +136,11 @@ sealed class Choice<out T> {
}
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<*>) {
Expand Down Expand Up @@ -400,6 +407,16 @@ sealed class CommandArgument<out T> : Option() {
override fun toString(): String = "IntegerArgument(name=$name, value=$value)"
}

class NumberArgument(
override val name: String,
override val value: Double
) : CommandArgument<Double>() {
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
Expand Down Expand Up @@ -509,6 +526,10 @@ sealed class CommandArgument<out T> : 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)
)
Expand Down
3 changes: 2 additions & 1 deletion core/api/core.api
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ 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
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
Expand All @@ -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.
Expand Down
31 changes: 20 additions & 11 deletions core/src/main/kotlin/entity/interaction/Interaction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -275,6 +274,11 @@ sealed class OptionValue<out T>(val value: T) {
override fun toString(): String = "IntOptionValue(value=$value)"
}


class NumberOptionValue(value: Double) : OptionValue<Double>(value) {
override fun toString(): String = "DoubleOptionValue(value=$value)"
}

class StringOptionValue(value: String) : OptionValue<String>(value) {
override fun toString(): String = "StringOptionValue(value=$value)"
}
Expand All @@ -291,6 +295,7 @@ sealed class OptionValue<out T>(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)
Expand All @@ -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 -> {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) }
Expand Down
11 changes: 11 additions & 0 deletions rest/src/main/kotlin/builder/interaction/OptionsBuilder.kt
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,17 @@ class IntChoiceBuilder(name: String, description: String) :
}
}

@KordPreview
@KordDsl
class NumberChoiceBuilder(name: String, description: String) :
BaseChoiceBuilder<Double>(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) :
Expand Down

0 comments on commit 3dd19cc

Please sign in to comment.