Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve slash command API and add support for components #310

Merged
merged 23 commits into from
Jun 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
4975ced
Make slash command creation eager
BartArys May 8, 2021
0773907
Fix typo in InteractionBehavior
BartArys May 8, 2021
90290f1
Don't compute supplier in InteractionBehavior
BartArys May 9, 2021
f791645
Specify withStrategy for Interactions
BartArys May 9, 2021
05bad6a
Introduce type to command options
BartArys May 10, 2021
f2aab31
Add KordDsl to builders
BartArys May 10, 2021
62b0561
Add allowedMentions builder functions
BartArys May 14, 2021
a1b3fa6
Add permission edits to guild commands
BartArys May 25, 2021
a440dc7
Make full member available for guild contexts
BartArys May 30, 2021
e047ba9
Support buttons/components (#303)
DRSchlaubi Jun 9, 2021
d64c7d3
Add core versions of components
BartArys Jun 11, 2021
5237de5
Restructure and document ButtonBuilder
BartArys Jun 11, 2021
50ec6e8
Remove ActionRowContainerBuilder
BartArys Jun 11, 2021
5958cab
Make ComponentInteraction message nullable
BartArys Jun 11, 2021
7c68dc2
Add missing components to interaction builders
BartArys Jun 11, 2021
22c8a17
Add missing ComponentInteraction behavior
BartArys Jun 11, 2021
fa3adbb
Fix withStrategy for ComponentInteractionBehavior
BartArys Jun 11, 2021
79938e8
Implement ComponentInteractionBehavior
BartArys Jun 11, 2021
f1573a6
Move component builders directory
BartArys Jun 11, 2021
de13dfa
Merge branch '0.7.x' into changes/0.7.x/slash-command-improvements
BartArys Jun 12, 2021
89ee61f
Fix interaction embeds optionality
BartArys Jun 12, 2021
175e06e
Make CommandInteraction#guildId optional
BartArys Jun 12, 2021
f1e310e
Make MessageModifyBuilder components vals
BartArys Jun 12, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion buildSrc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ dependencies {
implementation(kotlin("gradle-plugin-api", version = "1.5.0"))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

U sure this works? buildSrc is really slow at upgrading the Kotlin version and if it's to new it get's mad

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The version seems to exist, the CI doesn't fail because of it and building it locally with gradle clean build --no-build-cache doesn't seem to produce any errors.

If you have any issues building this yourself because of this, please do share a stacktrace and I'll look into it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's not the problem the version exist as soon as the new gradle plugin version is out
We need to wait for the gradle release adding support for the Kotlin version but if the build works for you i guess it works now

implementation(gradleApi())
implementation(localGroovy())
}
}
140 changes: 140 additions & 0 deletions common/src/main/kotlin/entity/DiscordComponent.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
package dev.kord.common.entity

import dev.kord.common.annotation.KordPreview
import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalBoolean
import kotlinx.serialization.KSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder

/**
* Represent a [intractable component within a message sent in Discord](https://discord.com/developers/docs/interactions/message-components#what-are-components).
*
* @property type the [ComponentType] of the component
* @property style the [ButtonStyle] of the component (if it is a button)
* @property style the text that appears on the button (if the component is a button)
* @property emoji an [DiscordPartialEmoji] that appears on the button (if the component is a button)
* @property customId a developer-defined identifier for the button, max 100 characters
* @property url a url for link-style buttons
* @property disabled whether the button is disabled, default `false`
* @property components a list of child components (for action rows)
*/
@KordPreview
@Serializable
data class DiscordComponent(
val type: ComponentType,
val style: Optional<ButtonStyle> = Optional.Missing(),
val label: Optional<String> = Optional.Missing(),
val emoji: Optional<DiscordPartialEmoji> = Optional.Missing(),
@SerialName("custom_id")
val customId: Optional<String> = Optional.Missing(),
val url: Optional<String> = Optional.Missing(),
val disabled: OptionalBoolean = OptionalBoolean.Missing,
val components: Optional<List<DiscordComponent>> = Optional.Missing()
)

/**
* Representation of different [DiscordComponent] types.
*
* @property value the raw type value used by the Discord API
*/
@KordPreview
@Serializable(with = ComponentType.Serializer::class)
sealed class ComponentType(val value: Int) {

/**
* Fallback type used for types that haven't been added to Kord yet.
*/
class Unknown(value: Int) : ComponentType(value)

/**
* A container for other components.
*/
object ActionRow : ComponentType(1)

/**
* A clickable button.
*/
object Button : ComponentType(2)

companion object Serializer : KSerializer<ComponentType> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ComponentType", PrimitiveKind.INT)

override fun deserialize(decoder: Decoder): ComponentType =
when (val value = decoder.decodeInt()) {
1 -> ActionRow
2 -> Button
else -> Unknown(value)
}

override fun serialize(encoder: Encoder, value: ComponentType) = encoder.encodeInt(value.value)
}
}

/**
* Representation of different ButtonStyles.
*
* A cheat sheet on how the styles look like can be found [here](https://discord.com/assets/7bb017ce52cfd6575e21c058feb3883b.png)
*
* @see ComponentType.Button
*/
@KordPreview
@Serializable(with = ButtonStyle.Serializer::class)
sealed class ButtonStyle(val value: Int) {

/**
* A fallback style used for styles that haven't been added to Kord yet.
*/
class Unknown(value: Int) : ButtonStyle(value)

/**
* Blurple.
* Requires: [DiscordComponent.customId]
*/
object Primary : ButtonStyle(1)

/**
* Grey.
* Requires: [DiscordComponent.customId]
*/
object Secondary : ButtonStyle(2)

/**
* Green
* Requires: [DiscordComponent.customId]
*/
object Success : ButtonStyle(3)

/**
* Red.
* Requires: [DiscordComponent.customId]
*/
object Danger : ButtonStyle(4)

/**
* Grey, navigates to an URL.
* Requires: [DiscordComponent.url]
*/
object Link : ButtonStyle(5)

companion object Serializer : KSerializer<ButtonStyle> {
override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor("ButtonStyle", PrimitiveKind.INT)

override fun deserialize(decoder: Decoder): ButtonStyle =
when (val value = decoder.decodeInt()) {
1 -> Primary
2 -> Secondary
3 -> Success
4 -> Danger
5 -> Link
else -> Unknown(value)
}

override fun serialize(encoder: Encoder, value: ButtonStyle) = encoder.encodeInt(value.value)
}
}
4 changes: 2 additions & 2 deletions common/src/main/kotlin/entity/DiscordEmoji.kt
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ data class DiscordUpdatedEmojis(
*/
@Serializable
data class DiscordPartialEmoji(
val id: Snowflake?,
val name: String?,
val id: Snowflake? = null,
val name: String? = null,
val animated: OptionalBoolean = OptionalBoolean.Missing,
)
6 changes: 6 additions & 0 deletions common/src/main/kotlin/entity/DiscordMessage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import kotlin.contracts.contract
* @param stickers The stickers sent with the message (bots currently can only receive messages with stickers, not send).
* @param referencedMessage the message associated with [messageReference].
* @param applicationId if the message is a response to an [Interaction][DiscordInteraction], this is the id of the interaction's application
* @param components a list of [components][DiscordComponent] which have been added to this message
*/
@Serializable
data class DiscordMessage(
Expand Down Expand Up @@ -103,6 +104,11 @@ data class DiscordMessage(
val stickers: Optional<List<DiscordMessageSticker>> = Optional.Missing(),
@SerialName("referenced_message")
val referencedMessage: Optional<DiscordMessage?> = Optional.Missing(),
/*
* don't trust the docs:
* This is a list even though the docs say it's a component
*/
val components: Optional<List<DiscordComponent>> = Optional.Missing(),
val interaction: Optional<DiscordMessageInteraction> = Optional.Missing()
)

Expand Down
Loading