Skip to content

Commit

Permalink
Add select menus
Browse files Browse the repository at this point in the history
Signed-off-by: shedaniel <daniel@shedaniel.me>
  • Loading branch information
shedaniel committed Sep 17, 2021
1 parent 2bc7e31 commit d243deb
Show file tree
Hide file tree
Showing 7 changed files with 115 additions and 3 deletions.
8 changes: 8 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,13 @@ task discordApiJar(type: Jar, dependsOn: [compileDiscord_apiKotlin]) {
archiveVersion = "1.0." + (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : System.getenv("GITHUB_RUN_NUMBER"))
}

task sourcesDiscordApiJar(type: Jar, dependsOn: discord_apiClasses) {
archiveBaseName = "linkie-discord-api"
archiveVersion = "1.0." + (System.getenv("GITHUB_RUN_NUMBER") == null ? "9999" : System.getenv("GITHUB_RUN_NUMBER"))
archiveClassifier = "sources"
from sourceSets.discord_api.allSource
}

build.finalizedBy mainJar

compileKotlin {
Expand All @@ -141,6 +148,7 @@ publishing {
artifactId = "linkie-discord-api"
version = discordApiJar.archiveVersion.get()
artifact(discordApiJar)
artifact(sourcesDiscordApiJar)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@
package me.shedaniel.linkie.discord.utils

import discord4j.core.`object`.component.Button
import discord4j.core.`object`.component.SelectMenu
import discord4j.core.`object`.reaction.ReactionEmoji
import discord4j.core.event.domain.interaction.SelectMenuInteractEvent
import me.shedaniel.linkie.discord.utils.extensions.getOrNull

fun ActionComponentAccepter.primaryButton(label: String, disabled: Boolean = false, action: ComponentAction = {}) = customId().also { id ->
add(Button.primary(id, label).disabled(disabled), id.componentFilter, action)
Expand Down Expand Up @@ -78,5 +81,80 @@ fun ActionComponentAccepter.linkButton(label: String, emoji: ReactionEmoji, url:
add(Button.link(url, emoji, label).disabled(disabled))

fun ActionComponentAccepter.dismissButton() = secondaryButton("Dismiss", "".discordEmote) {
it?.delete()?.subscribe()
it.message.getOrNull()?.delete()?.subscribe()
}

fun ActionComponentAccepter.selectMenu(spec: SelectMenuBuilder.() -> Unit) = customId().also { id ->
val (menu, action) = spec.build(id)
add(menu, id.componentFilter, action)
}

class SelectMenuBuilder(
var options: MutableList<SelectMenu.Option> = mutableListOf(),
var disabled: Boolean = false,
var placeholder: String? = null,
var minValues: Int? = null,
var maxValues: Int? = null,
var action: ComponentAction = {},
) {
fun build(customId: String): SelectMenu {
var menu = SelectMenu.of(customId, options).disabled(disabled)
if (placeholder != null) menu = menu.withPlaceholder(placeholder!!)
if (minValues != null) menu = menu.withMinValues(minValues!!)
if (maxValues != null) menu = menu.withMaxValues(maxValues!!)
return menu
}

fun addOptions(options: Collection<SelectMenu.Option>) {
this.options.addAll(options)
}

fun addOptions(vararg options: SelectMenu.Option) {
this.options.addAll(options)
}

fun addDefaultOption(
label: String,
value: String,
description: String? = null,
emoji: ReactionEmoji? = null,
) {
addOption(label, value, description, emoji, default = true)
}

fun addOption(
label: String,
value: String,
description: String? = null,
emoji: ReactionEmoji? = null,
default: Boolean = false,
) {
var option = if (default) SelectMenu.Option.ofDefault(label, value) else SelectMenu.Option.of(label, value)
if (description != null) option = option.withDescription(description)
if (emoji != null) option = option.withEmoji(emoji)
this.options.add(option)
}

fun disabled(disabled: Boolean = true) {
this.disabled = disabled
}

fun placeholder(placeholder: String?) {
this.placeholder = placeholder
}

fun minValues(minValues: Int?) {
this.minValues = minValues
}

fun maxValues(maxValues: Int?) {
this.maxValues = maxValues
}

fun action(action: MessageCreator.(SelectMenuInteractEvent, List<String>) -> Unit) {
this.action = {
it as SelectMenuInteractEvent
action(it, it.values)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package me.shedaniel.linkie.discord.utils

import discord4j.core.`object`.component.SelectMenu
import discord4j.core.spec.EmbedCreateSpec
import discord4j.core.spec.InteractionApplicationCommandCallbackSpec
import discord4j.core.spec.MessageCreateSpec
Expand Down Expand Up @@ -44,6 +45,9 @@ fun (ImmutableWebhookMessageEditRequest.Builder.() -> Unit).build(): WebhookMess
fun (MessageCreatorComplex.() -> Unit).build(): MessageCreatorComplex =
MessageCreatorComplex().also { this(it) }

fun (SelectMenuBuilder.() -> Unit).build(customId: String): Pair<SelectMenu, ComponentAction> =
SelectMenuBuilder().also { this(it) }.let { it.build(customId) to it.action }

@JvmName("buildLayoutComponentsBuilderUnit")
fun (LayoutComponentsBuilder.() -> Unit).build(): LayoutComponentsBuilder =
LayoutComponentsBuilder().also(this)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import discord4j.core.event.domain.interaction.ComponentInteractEvent
import java.util.*

typealias ComponentFilter = (ComponentInteractEvent) -> Boolean
typealias ComponentAction = MessageCreator.(Message?) -> Unit
typealias ComponentAction = MessageCreator.(ComponentInteractEvent) -> Unit

fun customId(): String = UUID.randomUUID().toString()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ fun (LayoutComponentsBuilder.() -> Unit).compile(client: GatewayDiscordClient, u
}, {
sentAny = true
})
action.invoke(msgCreator, event.message.getOrNull())
action.invoke(msgCreator, event)
if (!sentAny) {
event.acknowledge().subscribe()
}
Expand Down
6 changes: 6 additions & 0 deletions src/main/kotlin/me/shedaniel/linkie/discord/LinkieBot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,14 @@ import me.shedaniel.linkie.discord.scripting.LinkieScripting
import me.shedaniel.linkie.discord.scripting.push
import me.shedaniel.linkie.discord.tricks.TricksManager
import me.shedaniel.linkie.discord.utils.CommandContext
import me.shedaniel.linkie.discord.utils.dangerButton
import me.shedaniel.linkie.discord.utils.discordEmote
import me.shedaniel.linkie.discord.utils.discriminatedName
import me.shedaniel.linkie.discord.utils.dismissButton
import me.shedaniel.linkie.discord.utils.primaryButton
import me.shedaniel.linkie.discord.utils.selectMenu
import me.shedaniel.linkie.discord.utils.setTimestampToNow
import me.shedaniel.linkie.discord.utils.use
import me.shedaniel.linkie.namespaces.LegacyYarnNamespace
import me.shedaniel.linkie.namespaces.MCPNamespace
import me.shedaniel.linkie.namespaces.MojangHashedNamespace
Expand Down
16 changes: 16 additions & 0 deletions src/testDiscordApi/kotlin/TestBot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import me.shedaniel.linkie.discord.scommands.optNullable
import me.shedaniel.linkie.discord.scommands.string
import me.shedaniel.linkie.discord.utils.CommandContext
import me.shedaniel.linkie.discord.utils.dangerButton
import me.shedaniel.linkie.discord.utils.discordEmote
import me.shedaniel.linkie.discord.utils.dismissButton
import me.shedaniel.linkie.discord.utils.primaryButton
import me.shedaniel.linkie.discord.utils.selectMenu
import me.shedaniel.linkie.discord.utils.use
import kotlin.test.Test

Expand Down Expand Up @@ -65,6 +67,7 @@ class HelloCommand : Command {
class ButtonCommand : OptionlessCommand {
override suspend fun execute(ctx: CommandContext) = ctx.use {
var count = 0
var lastSelected = 0
message.replyComplex {
layout {
row {
Expand All @@ -81,6 +84,19 @@ class ButtonCommand : OptionlessCommand {
}
}
}
row {
selectMenu {
addOption("Epic Entry 1", "entryOne", description = "Epic description", emoji = "".discordEmote)
addOption("Epic Entry 2", "entryTwo", description = "Epic description", emoji = "".discordEmote)
options = options.mapIndexed { index, option -> option.withDefault(index == lastSelected) }.toMutableList()
minValues(1)
maxValues(1)
action { _, options ->
lastSelected = this@selectMenu.options.indexOfFirst { it.value == options.first() }
reply("You have selected ${options.first()}")
}
}
}
}
embed {
description("hello")
Expand Down

0 comments on commit d243deb

Please sign in to comment.