Skip to content

Commit

Permalink
Application commands improvements (#374)
Browse files Browse the repository at this point in the history
* fix optional function builders

* fix options list

* fix target_id property

* add target properties to user and message interactions

* Add missing component options (#377)

* Fix NPE on ThreadChannelDelete (#373)

* Add missing component options

Co-authored-by: shilu <[email protected]>

* allow to create an application command behavior

* add some missing typesafe option getters (#378)

* Fix NPE on ThreadChannelDelete (#373)

* add some missing typesafe option getters

Co-authored-by: shilu <[email protected]>

Co-authored-by: Potatoboy99999 <[email protected]>
Co-authored-by: shilu <[email protected]>
Co-authored-by: Xander <[email protected]>
  • Loading branch information
4 people authored Aug 28, 2021
1 parent d8134f3 commit df1875d
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 37 deletions.
16 changes: 8 additions & 8 deletions common/src/main/kotlin/entity/Interactions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -279,8 +279,8 @@ sealed class InteractionType(val type: Int) {
data class InteractionCallbackData(
val id: OptionalSnowflake = OptionalSnowflake.Missing,
val type: Optional<ApplicationCommandType> = Optional.Missing(),
@SerialName("target_user")
val targetUser: OptionalSnowflake = OptionalSnowflake.Missing,
@SerialName("target_id")
val targetId: OptionalSnowflake = OptionalSnowflake.Missing,
val name: Optional<String> = Optional.Missing(),
val resolved: Optional<ResolvedObjects> = Optional.Missing(),
val options: Optional<List<Option>> = Optional.Missing(),
Expand Down Expand Up @@ -422,8 +422,8 @@ sealed class CommandArgument<out T> : Option() {

class IntegerArgument(
override val name: String,
override val value: Int
) : CommandArgument<Int>() {
override val value: Long
) : CommandArgument<Long>() {
override val type: ApplicationCommandOptionType
get() = ApplicationCommandOptionType.Integer

Expand Down Expand Up @@ -528,7 +528,7 @@ sealed class CommandArgument<out T> : Option() {
Snowflake.serializer(),
value.value
)
is IntegerArgument -> encodeIntElement(descriptor, 1, value.value)
is IntegerArgument -> encodeLongElement(descriptor, 1, value.value)
is NumberArgument -> encodeDoubleElement(descriptor, 1, value.value)
is StringArgument -> encodeStringElement(descriptor, 1, value.value)
}
Expand All @@ -548,7 +548,7 @@ sealed class CommandArgument<out T> : Option() {
name, json.decodeFromJsonElement(String.serializer(), element)
)
ApplicationCommandOptionType.Integer -> IntegerArgument(
name, json.decodeFromJsonElement(Int.serializer(), element)
name, json.decodeFromJsonElement(Long.serializer(), element)
)

ApplicationCommandOptionType.Number -> NumberArgument(
Expand Down Expand Up @@ -609,8 +609,8 @@ data class CommandGroup(
get() = ApplicationCommandOptionType.SubCommandGroup
}

fun CommandArgument<*>.int(): Int {
return value as? Int ?: error("$value wasn't an Int.")
fun CommandArgument<*>.int(): Long {
return value as? Long ?: error("$value wasn't an int.")
}


Expand Down
29 changes: 29 additions & 0 deletions core/src/main/kotlin/Unsafe.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import dev.kord.core.behavior.channel.*
import dev.kord.core.behavior.channel.threads.PrivateThreadParentChannelBehavior
import dev.kord.core.behavior.channel.threads.ThreadChannelBehavior
import dev.kord.core.behavior.channel.threads.ThreadParentChannelBehavior
import dev.kord.core.behavior.interaction.ApplicationCommandInteractionBehavior
import dev.kord.core.behavior.interaction.ComponentInteractionBehavior
import dev.kord.core.entity.interaction.ApplicationCommandInteraction
import dev.kord.rest.service.InteractionService

/**
Expand Down Expand Up @@ -94,6 +96,33 @@ class Unsafe(private val kord: Kord) {
id, channelId, kord, kord.defaultSupplier
)

fun applicationCommandInteraction(
id: Snowflake,
channelId: Snowflake,
token: String,
applicationId: Snowflake
): ApplicationCommandInteractionBehavior {
return ApplicationCommandInteractionBehavior(id, channelId, token, applicationId, kord)
}


fun globalApplicationCommand(
applicationId: Snowflake,
id: Snowflake
): GlobalApplicationCommandBehavior {
return GlobalApplicationCommandBehavior(applicationId, id, kord.rest.interaction)
}


fun globalApplicationCommand(
applicationId: Snowflake,
guildId: Snowflake,
id: Snowflake
): GuildApplicationCommandBehavior {
return GuildApplicationCommandBehavior(guildId, applicationId, id, kord.rest.interaction)
}


override fun toString(): String {
return "Unsafe"
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,8 @@
package dev.kord.core.behavior.interaction

import dev.kord.common.annotation.KordPreview
import dev.kord.common.entity.InteractionResponseType
import dev.kord.common.entity.MessageFlag
import dev.kord.common.entity.MessageFlags
import dev.kord.common.entity.optional.Optional
import dev.kord.rest.builder.message.create.EphemeralInteractionResponseCreateBuilder
import dev.kord.rest.builder.message.create.PublicInteractionResponseCreateBuilder
import dev.kord.rest.json.request.InteractionApplicationCommandCallbackData
import dev.kord.rest.json.request.InteractionResponseCreateRequest
import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract
import dev.kord.common.entity.Snowflake
import dev.kord.core.Kord
import dev.kord.core.supplier.EntitySupplier

/**
* The behavior of a [Discord Interaction](https://discord.com/developers/docs/interactions/slash-commands#interaction)
Expand All @@ -20,3 +11,27 @@ import kotlin.contracts.contract

interface ApplicationCommandInteractionBehavior : InteractionBehavior

internal fun ApplicationCommandInteractionBehavior(
id: Snowflake,
channelId: Snowflake,
token: String,
applicationId: Snowflake,
kord: Kord,
supplier: EntitySupplier = kord.defaultSupplier
) = object : ApplicationCommandInteractionBehavior {

override val applicationId: Snowflake
get() = applicationId

override val token: String
get() = token
override val channelId: Snowflake
get() = channelId
override val kord: Kord
get() = kord
override val id: Snowflake
get() = id
override val supplier: EntitySupplier
get() = supplier

}
3 changes: 2 additions & 1 deletion core/src/main/kotlin/cache/data/ComponentData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ data class ComponentData(
components.mapList { from(it) },
placeholder = placeholder,
minValues = minValues,
maxValues = maxValues
maxValues = maxValues,
options = options.mapList { SelectOptionData.from(it) }
)
}

Expand Down
4 changes: 2 additions & 2 deletions core/src/main/kotlin/cache/data/InteractionData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ data class ResolvedObjectsData(
data class ApplicationInteractionData(
val id: OptionalSnowflake = OptionalSnowflake.Missing,
val type: Optional<ApplicationCommandType> = Optional.Missing(),
val targetUser: OptionalSnowflake = OptionalSnowflake.Missing,
val targetId: OptionalSnowflake = OptionalSnowflake.Missing,
val name: Optional<String> = Optional.Missing(),
val options: Optional<List<OptionData>> = Optional.Missing(),
val resolvedObjectsData: Optional<ResolvedObjectsData> = Optional.Missing(),
Expand All @@ -99,7 +99,7 @@ data class ApplicationInteractionData(
ApplicationInteractionData(
id,
type,
targetUser,
targetId,
name,
options.map { it.map { OptionData.from(it) } },
resolved.map { ResolvedObjectsData.from(it, guildId) },
Expand Down
23 changes: 18 additions & 5 deletions core/src/main/kotlin/entity/interaction/ContextInteraction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import dev.kord.core.Kord
import dev.kord.core.behavior.UserBehavior
import dev.kord.core.behavior.interaction.ApplicationCommandInteractionBehavior
import dev.kord.core.cache.data.InteractionData
import dev.kord.core.entity.Member
import dev.kord.core.entity.Message
import dev.kord.core.entity.User
import dev.kord.core.entity.application.GuildUserCommand
import dev.kord.core.supplier.EntitySupplier
import dev.kord.core.supplier.EntitySupplyStrategy
import java.util.*
Expand Down Expand Up @@ -85,7 +82,15 @@ class GlobalChatInputCommandInteraction(
*/
sealed interface UserCommandInteraction : ApplicationCommandInteraction {

val users get() = resolvedObjects!!.users
val targetId: Snowflake get() = data.data.targetId.value!!

val targetBehavior: UserBehavior get() = UserBehavior(targetId, kord)

suspend fun getTarget(): User = supplier.getUser(targetId)

suspend fun getTargetOrNull(): User? = supplier.getUserOrNull(targetId)

val users get() = resolvedObjects!!.users!!
}

/**
Expand Down Expand Up @@ -129,7 +134,15 @@ class GlobalUserCommandInteraction(
*/
sealed interface MessageCommandInteraction : ApplicationCommandInteraction {

val messages get() = resolvedObjects!!.messages
val targetId: Snowflake get() = data.data.targetId.value!!

val targetBehavior: UserBehavior get() = UserBehavior(targetId, kord)

suspend fun getTarget(): User = supplier.getUser(targetId)

suspend fun getTargetOrNull(): User? = supplier.getUserOrNull(targetId)

val messages get() = resolvedObjects!!.messages!!

}

Expand Down
16 changes: 13 additions & 3 deletions core/src/main/kotlin/entity/interaction/Interaction.kt
Original file line number Diff line number Diff line change
Expand Up @@ -113,12 +113,22 @@ sealed interface InteractionCommand : KordObject {

val strings: Map<String, String> get() = filterOptions()

val integers: Map<String, Int> get() = filterOptions()
val integers: Map<String, Long> get() = filterOptions()

val numbers: Map<String, Double> get() = filterOptions()

val booleans: Map<String, Boolean> get() = filterOptions()

val users: Map<String, User> get() = filterOptions()

val members: Map<String, Member> get() = filterOptions()

val channels: Map<String, ResolvedChannel> get() = filterOptions()

val roles: Map<String, Role> get() = filterOptions()

val mentionables: Map<String, Entity> get() = filterOptions()

private inline fun <reified T> filterOptions(): Map<String, T> {
return buildMap {
options.onEach { (key, value) ->
Expand Down Expand Up @@ -281,7 +291,7 @@ sealed class OptionValue<out T>(val value: T) {
override fun toString(): String = "ChannelOptionValue(value=$value)"
}

class IntOptionValue(value: Int) : OptionValue<Int>(value) {
class IntOptionValue(value: Long) : OptionValue<Long>(value) {
override fun toString(): String = "IntOptionValue(value=$value)"
}

Expand Down Expand Up @@ -459,7 +469,7 @@ fun OptionValue<*>.string() = value.toString()
fun OptionValue<*>.boolean() = value as Boolean


fun OptionValue<*>.int() = value as Int
fun OptionValue<*>.int() = value as Long


fun OptionValue<*>.number() = value as Double
Expand Down
6 changes: 3 additions & 3 deletions core/src/test/kotlin/interaction/CommandTypesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ class CommandsTypeTests {
val command = InteractionCommand(data, mockKord())
assert(command is RootCommand)
command as RootCommand
assertEquals(1, command.options["argument"]?.int())
assertEquals(1L, command.integers["argument"])
assertEquals("root", command.rootName)

}
Expand All @@ -66,7 +66,7 @@ class CommandsTypeTests {
val command = InteractionCommand(data, mockKord())
assert(command is SubCommand)
command as SubCommand
assertEquals(1, command.options["argument"]?.int())
assertEquals(1L, command.integers["argument"])
assertEquals("root", command.rootName)
assertEquals("subCommand", command.name)

Expand All @@ -79,7 +79,7 @@ class CommandsTypeTests {
val command = InteractionCommand(data, mockKord())
assert(command is GroupCommand)
command as GroupCommand
assertEquals(1, command.options["argument"]?.int())
assertEquals(1L, command.integers["argument"])
assertEquals("root", command.rootName)
assertEquals("group", command.groupName)
assertEquals("subCommand", command.name)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,21 @@ class MultiApplicationCommandBuilder {
val commands = mutableListOf<ApplicationCommandCreateBuilder>()

@OptIn(ExperimentalContracts::class)
inline fun message(name: String, builder: MessageCommandCreateBuilder.() -> Unit) {
inline fun message(name: String, builder: MessageCommandCreateBuilder.() -> Unit = {}) {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
commands += MessageCommandCreateBuilder(name).apply(builder)
}

@OptIn(ExperimentalContracts::class)
inline fun user(name: String, builder: UserCommandCreateBuilder.() -> Unit) {
inline fun user(name: String, builder: UserCommandCreateBuilder.() -> Unit = {}) {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
commands += UserCommandCreateBuilder(name).apply(builder)
}
@OptIn(ExperimentalContracts::class)
inline fun input(
name: String,
description: String,
builder: ChatInputCreateBuilder.() -> Unit) {
builder: ChatInputCreateBuilder.() -> Unit = {}) {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
commands += ChatInputCreateBuilder(name, description).apply(builder)
}
Expand Down

0 comments on commit df1875d

Please sign in to comment.