diff --git a/CHANGELOG.md b/CHANGELOG.md index ff1fbc69857..9e895e42333 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,11 +10,24 @@ * `MessageModifyBuilder` * `EditWebhookMessageBuilder` * `InteractionResponseModifyRequest` +* `FollowupMessageBuilder` +* `PublicFollowupMessageModifyBuilder` +* `EphemeralFollowupMessageModifyBuilder` +* `PublicFollowupMessageCreateBuilder` +* `EphemeralFollowupMessageCreateBuilder` +* `FollowupMessageModifyRequest` +* `ComponentInteraction` ## Changes * Message-related builders have been changed to accept `null` (for non-collections) and "empty list" (for collections) when editing a message. This makes it possible to remove fields from a message without providing a substitution. +* `FollowupMessageBuilder` no longer has the `tts` field, since it does not apply to all its subclasses. + +## Fixes + +* `ActionRowComponent` properly returns its children. +* `ComponentInteraction#button` is now nullable as its documentation implies. # 0.7.0 diff --git a/core/src/main/kotlin/cache/data/ComponentData.kt b/core/src/main/kotlin/cache/data/ComponentData.kt index 8d53f3c391e..db68257d90e 100644 --- a/core/src/main/kotlin/cache/data/ComponentData.kt +++ b/core/src/main/kotlin/cache/data/ComponentData.kt @@ -6,6 +6,7 @@ import dev.kord.common.entity.DiscordComponent import dev.kord.common.entity.DiscordPartialEmoji import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.OptionalBoolean +import dev.kord.common.entity.optional.mapList import kotlinx.serialization.Serializable @Serializable @@ -23,7 +24,7 @@ data class ComponentData( companion object { - fun from(entity: DiscordComponent) = with(entity) { + fun from(entity: DiscordComponent): ComponentData = with(entity) { ComponentData( type, style, @@ -31,7 +32,8 @@ data class ComponentData( emoji, customId, url, - disabled + disabled, + components.mapList { from(it) } ) } diff --git a/core/src/main/kotlin/entity/interaction/Interaction.kt b/core/src/main/kotlin/entity/interaction/Interaction.kt index a399fa2acf3..bd1424603fc 100644 --- a/core/src/main/kotlin/entity/interaction/Interaction.kt +++ b/core/src/main/kotlin/entity/interaction/Interaction.kt @@ -1,7 +1,10 @@ package dev.kord.core.entity.interaction import dev.kord.common.annotation.KordPreview -import dev.kord.common.entity.* +import dev.kord.common.entity.CommandArgument +import dev.kord.common.entity.InteractionType +import dev.kord.common.entity.Permissions +import dev.kord.common.entity.Snowflake import dev.kord.common.entity.optional.* import dev.kord.core.Kord import dev.kord.core.KordObject @@ -11,25 +14,18 @@ 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.EphemeralInteractionResponseBehavior import dev.kord.core.behavior.interaction.InteractionBehavior -import dev.kord.core.behavior.interaction.PublicInteractionResponseBehavior 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.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 -import dev.kord.rest.builder.interaction.UpdateMessageInteractionResponseCreateBuilder -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 /** * An instance of [Interaction] (https://discord.com/developers/docs/interactions/slash-commands#interaction) @@ -385,9 +381,11 @@ class ComponentInteraction( * * @see Component */ - val component: ButtonComponent + val component: ButtonComponent? get() = message?.components.orEmpty() - .filterIsInstance().first { it.customId == componentId } + .filterIsInstance() + .flatMap { it.buttons } + .firstOrNull { it.customId == componentId } override fun withStrategy(strategy: EntitySupplyStrategy<*>): ComponentInteraction = ComponentInteraction( diff --git a/rest/api/rest.api b/rest/api/rest.api index 46f00d8e9ac..e00724704cb 100644 --- a/rest/api/rest.api +++ b/rest/api/rest.api @@ -695,10 +695,10 @@ public final class dev/kord/rest/builder/interaction/EphemeralFollowupMessageCre public fun getComponents ()Ljava/util/List; public fun getContent ()Ljava/lang/String; public fun getEmbeds ()Ljava/util/List; - public fun getTts ()Ljava/lang/Boolean; + public final fun getTts ()Ljava/lang/Boolean; public fun setAllowedMentions (Ldev/kord/rest/builder/message/AllowedMentionsBuilder;)V public fun setContent (Ljava/lang/String;)V - public fun setTts (Ljava/lang/Boolean;)V + public final fun setTts (Ljava/lang/Boolean;)V public fun toRequest ()Ldev/kord/rest/json/request/MultipartFollowupMessageCreateRequest; public synthetic fun toRequest ()Ljava/lang/Object; } @@ -709,10 +709,10 @@ public final class dev/kord/rest/builder/interaction/EphemeralFollowupMessageMod public fun getComponents ()Ljava/util/List; public fun getContent ()Ljava/lang/String; public fun getEmbeds ()Ljava/util/List; - public fun getTts ()Ljava/lang/Boolean; public fun setAllowedMentions (Ldev/kord/rest/builder/message/AllowedMentionsBuilder;)V + public fun setComponents (Ljava/util/List;)V public fun setContent (Ljava/lang/String;)V - public fun setTts (Ljava/lang/Boolean;)V + public fun setEmbeds (Ljava/util/List;)V public fun toRequest ()Ldev/kord/rest/json/request/FollowupMessageModifyRequest; public synthetic fun toRequest ()Ljava/lang/Object; } @@ -748,9 +748,7 @@ public abstract interface class dev/kord/rest/builder/interaction/FollowupMessag public abstract fun getComponents ()Ljava/util/List; public abstract fun getContent ()Ljava/lang/String; public abstract fun getEmbeds ()Ljava/util/List; - public abstract fun getTts ()Ljava/lang/Boolean; public abstract fun setAllowedMentions (Ldev/kord/rest/builder/message/AllowedMentionsBuilder;)V - public abstract fun setTts (Ljava/lang/Boolean;)V } public final class dev/kord/rest/builder/interaction/FollowupMessageBuildersKt { @@ -794,10 +792,10 @@ public final class dev/kord/rest/builder/interaction/PublicFollowupMessageCreate public fun getContent ()Ljava/lang/String; public fun getEmbeds ()Ljava/util/List; public final fun getFiles ()Ljava/util/List; - public fun getTts ()Ljava/lang/Boolean; + public final fun getTts ()Ljava/lang/Boolean; public fun setAllowedMentions (Ldev/kord/rest/builder/message/AllowedMentionsBuilder;)V public fun setContent (Ljava/lang/String;)V - public fun setTts (Ljava/lang/Boolean;)V + public final fun setTts (Ljava/lang/Boolean;)V public fun toRequest ()Ldev/kord/rest/json/request/MultipartFollowupMessageCreateRequest; public synthetic fun toRequest ()Ljava/lang/Object; } @@ -811,10 +809,10 @@ public final class dev/kord/rest/builder/interaction/PublicFollowupMessageModify public fun getContent ()Ljava/lang/String; public fun getEmbeds ()Ljava/util/List; public final fun getFiles ()Ljava/util/List; - public fun getTts ()Ljava/lang/Boolean; public fun setAllowedMentions (Ldev/kord/rest/builder/message/AllowedMentionsBuilder;)V + public fun setComponents (Ljava/util/List;)V public fun setContent (Ljava/lang/String;)V - public fun setTts (Ljava/lang/Boolean;)V + public fun setEmbeds (Ljava/util/List;)V public fun toRequest ()Ldev/kord/rest/json/request/MultipartFollowupMessageModifyRequest; public synthetic fun toRequest ()Ljava/lang/Object; } diff --git a/rest/src/main/kotlin/builder/interaction/FollowupMessageBuilders.kt b/rest/src/main/kotlin/builder/interaction/FollowupMessageBuilders.kt index 59bd08b20c0..5f7adfdba10 100644 --- a/rest/src/main/kotlin/builder/interaction/FollowupMessageBuilders.kt +++ b/rest/src/main/kotlin/builder/interaction/FollowupMessageBuilders.kt @@ -6,12 +6,16 @@ import dev.kord.common.entity.optional.Optional import dev.kord.common.entity.optional.OptionalBoolean import dev.kord.common.entity.optional.delegate.delegate import dev.kord.common.entity.optional.map +import dev.kord.common.entity.optional.mapList import dev.kord.rest.builder.RequestBuilder import dev.kord.rest.builder.component.ActionRowBuilder import dev.kord.rest.builder.component.MessageComponentBuilder import dev.kord.rest.builder.message.AllowedMentionsBuilder import dev.kord.rest.builder.message.EmbedBuilder -import dev.kord.rest.json.request.* +import dev.kord.rest.json.request.FollowupMessageCreateRequest +import dev.kord.rest.json.request.FollowupMessageModifyRequest +import dev.kord.rest.json.request.MultipartFollowupMessageCreateRequest +import dev.kord.rest.json.request.MultipartFollowupMessageModifyRequest import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext import java.io.InputStream @@ -24,13 +28,11 @@ import kotlin.contracts.contract @KordPreview sealed interface FollowupMessageBuilder : RequestBuilder { - var tts: Boolean? - var allowedMentions: AllowedMentionsBuilder? - val embeds: MutableList + val embeds: MutableList? - val components: MutableList + val components: MutableList? val content: String? @@ -42,13 +44,52 @@ inline fun FollowupMessageBuilder.actionRow(builder: ActionRowBuilder.() callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - components.add(ActionRowBuilder().apply(builder)) + when (this) { + is EphemeralFollowupMessageCreateBuilder -> { + components.add(ActionRowBuilder().apply(builder)) + } + + is EphemeralFollowupMessageModifyBuilder -> { + components = (components ?: mutableListOf()).also { + it.add(ActionRowBuilder().apply(builder)) + } + } + + is PublicFollowupMessageCreateBuilder -> { + components.add(ActionRowBuilder().apply(builder)) + } + + is PublicFollowupMessageModifyBuilder -> { + components = (components ?: mutableListOf()).also { + it.add(ActionRowBuilder().apply(builder)) + } + } + } + } @KordPreview @OptIn(ExperimentalContracts::class) inline fun FollowupMessageBuilder.embed(builder: EmbedBuilder.() -> Unit) { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - embeds += EmbedBuilder().apply(builder) + + when(this){ + is EphemeralFollowupMessageCreateBuilder -> { + embeds.add(EmbedBuilder().apply(builder)) + } + is EphemeralFollowupMessageModifyBuilder -> { + embeds = (embeds ?: mutableListOf()).also { + it.add(EmbedBuilder().apply(builder)) + } + } + is PublicFollowupMessageCreateBuilder -> { + embeds.add(EmbedBuilder().apply(builder)) + } + is PublicFollowupMessageModifyBuilder -> { + embeds = (embeds ?: mutableListOf()).also { + it.add(EmbedBuilder().apply(builder)) + } + } + } } /** @@ -69,22 +110,19 @@ inline fun FollowupMessageBuilder.allowedMentions(block: AllowedMentionsB @KordDsl class PublicFollowupMessageModifyBuilder : FollowupMessageBuilder { - private var _content: Optional = Optional.Missing() + private var _content: Optional = Optional.Missing() override var content: String? by ::_content.delegate() - override val embeds: MutableList = mutableListOf() - - private var _tts: OptionalBoolean = OptionalBoolean.Missing - override var tts: Boolean? by ::_tts.delegate() + private var _embeds: Optional> = Optional.Missing() + override var embeds: MutableList? by ::_embeds.delegate() val files: MutableList> = mutableListOf() - - private var _allowedMentions: Optional = Optional.Missing() + private var _allowedMentions: Optional = Optional.Missing() override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate() - override val components: MutableList = mutableListOf() - + private var _components: Optional> = Optional.Missing() + override var components: MutableList? by ::_components.delegate() fun addFile(name: String, content: InputStream) { files += name to content @@ -93,13 +131,14 @@ class PublicFollowupMessageModifyBuilder : suspend fun addFile(path: Path) = withContext(Dispatchers.IO) { addFile(path.fileName.toString(), Files.newInputStream(path)) } + override fun toRequest(): MultipartFollowupMessageModifyRequest { return MultipartFollowupMessageModifyRequest( FollowupMessageModifyRequest( _content, - Optional.missingOnEmpty(embeds.map(EmbedBuilder::toRequest)), + _embeds.mapList { it.toRequest() }, _allowedMentions.map { it.build() }, - Optional.missingOnEmpty(components.map(MessageComponentBuilder::build)) + _components.mapList { it.build() }, ), files ) @@ -111,24 +150,24 @@ class PublicFollowupMessageModifyBuilder : @KordDsl class EphemeralFollowupMessageModifyBuilder : FollowupMessageBuilder { - private var _content: Optional = Optional.Missing() + private var _content: Optional = Optional.Missing() override var content: String? by ::_content.delegate() - private var _tts: OptionalBoolean = OptionalBoolean.Missing - override var tts: Boolean? by ::_tts.delegate() - - override val embeds: MutableList = mutableListOf() + private var _embeds: Optional> = Optional.Missing() + override var embeds: MutableList? by ::_embeds.delegate() private var _allowedMentions: Optional = Optional.Missing() override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate() - override val components: MutableList = mutableListOf() + private var _components: Optional> = Optional.Missing() + override var components: MutableList? by ::_components.delegate() override fun toRequest(): FollowupMessageModifyRequest { return FollowupMessageModifyRequest( content = _content, allowedMentions = _allowedMentions.map { it.build() }, - components = Optional.missingOnEmpty(components.map(MessageComponentBuilder::build)) + embeds = _embeds.mapList { it.toRequest() }, + components = _components.mapList { it.build() } ) } } @@ -141,20 +180,18 @@ class PublicFollowupMessageCreateBuilder : FollowupMessageBuilder = Optional.Missing() override var content: String? by ::_content.delegate() - private var _tts: OptionalBoolean = OptionalBoolean.Missing - override var tts: Boolean? by ::_tts.delegate() + var tts: Boolean? by ::_tts.delegate() private var _allowedMentions: Optional = Optional.Missing() override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate() val files: MutableList> = mutableListOf() + override val embeds: MutableList = mutableListOf() override val components: MutableList = mutableListOf() - - override fun toRequest(): MultipartFollowupMessageCreateRequest = MultipartFollowupMessageCreateRequest( FollowupMessageCreateRequest( @@ -178,7 +215,7 @@ class EphemeralFollowupMessageCreateBuilder : FollowupMessageBuilder = Optional.Missing() override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate() @@ -200,4 +237,4 @@ class EphemeralFollowupMessageCreateBuilder : FollowupMessageBuilder = Optional.Missing(), - val embeds: Optional> = Optional.Missing(), + val content: Optional = Optional.Missing(), + val embeds: Optional?> = Optional.Missing(), @SerialName("allowed_mentions") - val allowedMentions: Optional = Optional.Missing(), - val components: Optional> = Optional.Missing() + val allowedMentions: Optional = Optional.Missing(), + val components: Optional?> = Optional.Missing() ) @KordPreview