Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import io.github.freya022.botcommands.api.modals.ModalEvent
import io.github.freya022.botcommands.api.modals.annotations.ModalInput
import io.github.freya022.botcommands.api.modals.options.ModalOption
import io.github.freya022.botcommands.api.parameters.ParameterResolver
import net.dv8tion.jda.api.components.attachmentupload.AttachmentUpload
import net.dv8tion.jda.api.components.selections.EntitySelectMenu
import net.dv8tion.jda.api.components.selections.StringSelectMenu
import net.dv8tion.jda.api.components.textinput.TextInput
Expand All @@ -24,6 +25,7 @@ import kotlin.reflect.KType
* - [StringSelectMenu] : `List<String>`
* - [EntitySelectMenu] : [Mentions], `T` and `List<T>` where `T` is one of:
* [IMentionable], [Role], [User], [InputUser], [Member], [GuildChannel]
* - [AttachmentUpload] : `List` of [Message.Attachment]
*
* @param T Type of the implementation
* @param R Type of the returned resolved objects
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.github.freya022.botcommands.internal.modals.resolvers

import io.github.freya022.botcommands.api.core.service.annotations.Resolver
import io.github.freya022.botcommands.api.modals.ModalEvent
import io.github.freya022.botcommands.api.modals.options.ModalOption
import io.github.freya022.botcommands.api.parameters.TypedParameterResolver
import io.github.freya022.botcommands.api.parameters.resolvers.ModalParameterResolver
import net.dv8tion.jda.api.entities.Message.Attachment
import net.dv8tion.jda.api.interactions.modals.ModalMapping
import kotlin.reflect.typeOf

@Resolver
internal object ModalAttachmentListResolver :
TypedParameterResolver<ModalAttachmentListResolver, List<Attachment>>(typeOf<List<Attachment>>()),
ModalParameterResolver<ModalAttachmentListResolver, List<Attachment>> {

override suspend fun resolveSuspend(
option: ModalOption,
event: ModalEvent,
modalMapping: ModalMapping,
): List<Attachment> = modalMapping.asAttachmentList
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ internal val ModalMapping.valueAsString: String
STRING_SELECT -> asStringList.toString()
TEXT_INPUT -> asString
CHANNEL_SELECT, ROLE_SELECT, USER_SELECT, MENTIONABLE_SELECT -> asLongList.toString()
FILE_UPLOAD -> asAttachmentList.map { "${it.fileName} (${it.contentType}, ${it.size} B)" }.toString()
else -> toString()
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,7 @@ import io.github.freya022.botcommands.api.modals.options.ModalOption
import io.github.freya022.botcommands.api.parameters.ParameterResolver
import io.github.freya022.botcommands.api.parameters.ResolverRequest
import io.github.freya022.botcommands.api.parameters.resolvers.ModalParameterResolver
import io.github.freya022.botcommands.internal.modals.resolvers.ModalIMentionableResolverFactory
import io.github.freya022.botcommands.internal.modals.resolvers.ModalMentionsResolver
import io.github.freya022.botcommands.internal.modals.resolvers.ModalStringListResolver
import io.github.freya022.botcommands.internal.modals.resolvers.ModalStringResolver
import io.github.freya022.botcommands.internal.modals.resolvers.*
import io.github.freya022.botcommands.internal.parameters.ResolverContainer
import io.mockk.every
import io.mockk.mockk
Expand Down Expand Up @@ -54,6 +51,7 @@ object ModalInputResolverTests {
every { channels } returns [email protected]
every { getMentions() } returns [email protected]
}
private val attachments = listOf<Message.Attachment>(mockk())

@MethodSource("modalInputs")
@ParameterizedTest
Expand All @@ -62,16 +60,19 @@ object ModalInputResolverTests {
every { getServiceNamesForAnnotation(Resolver::class) } returns listOf(
"modalMentionsResolver",
"modalStringResolver",
"modalStringListResolver"
"modalStringListResolver",
"modalAttachmentListResolver",
)

every { findAnnotationOnService("modalMentionsResolver", Resolver::class) } returns Resolver(0)
every { findAnnotationOnService("modalStringResolver", Resolver::class) } returns Resolver(0)
every { findAnnotationOnService("modalStringListResolver", Resolver::class) } returns Resolver(0)
every { findAnnotationOnService("modalAttachmentListResolver", Resolver::class) } returns Resolver(0)

every { getService("modalMentionsResolver", ParameterResolver::class) } returns ModalMentionsResolver
every { getService("modalStringResolver", ParameterResolver::class) } returns ModalStringResolver
every { getService("modalStringListResolver", ParameterResolver::class) } returns ModalStringListResolver
every { getService("modalAttachmentListResolver", ParameterResolver::class) } returns ModalAttachmentListResolver
}
val resolvers = ResolverContainer(serviceContainer, listOf(ModalIMentionableResolverFactory))

Expand All @@ -82,6 +83,7 @@ object ModalInputResolverTests {
every { asString } returns STRING
every { asStringList } returns strings
every { asMentions } returns mentions
every { asAttachmentList } returns attachments
}

val value = runBlocking {
Expand Down Expand Up @@ -113,6 +115,7 @@ object ModalInputResolverTests {
arguments("Select menu channel", 12, channel),
arguments("Select menu channels", 13, channels),
arguments("Select menu mentions", 14, mentions),
arguments("Attachments", 15, attachments),
)
return listOf
}
Expand All @@ -136,5 +139,6 @@ object ModalInputResolverTests {
@Suppress("unused") selectedChannel: GuildChannel?,
@Suppress("unused") selectedChannels: List<GuildChannel>,
@Suppress("unused") selectedMentions: Mentions,
@Suppress("unused") attachments: List<Message.Attachment>,
) {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package dev.freya02.botcommands.jda.ktx.components

import net.dv8tion.jda.api.components.Component
import net.dv8tion.jda.api.components.attachmentupload.AttachmentUpload

class InlineAttachmentUpload(
val builder: AttachmentUpload.Builder,
) : InlineComponent {

override var uniqueId: Int
get() = builder.uniqueId
set(value) {
builder.setUniqueId(value)
}

/** The custom ID, can be used to pass data, then read in an interaction, see [AttachmentUpload.Builder.setCustomId] */
var customId: String
get() = builder.customId
set(value) {
builder.setCustomId(value)
}

/** Whether the user must upload files, see [AttachmentUpload.Builder.setRequired] */
var required: Boolean
get() = builder.isRequired
set(value) {
builder.setRequired(value)
}

/** Minimum and maximum amount of files a user can send, see [AttachmentUpload.Builder.setRequiredRange] */
var range: IntRange
get() = builder.minValues..builder.maxValues
set(value) {
builder.setRequiredRange(value.first, value.last)
}

/** Minimum amount of attachments the user has to send, see [AttachmentUpload.Builder.setMinValues] */
var minValues: Int
get() = builder.minValues
set(value) {
builder.setMinValues(value)
}

/** Maximum amount of attachments the user can send, see [AttachmentUpload.Builder.setMaxValues] */
var maxValues: Int
get() = builder.maxValues
set(value) {
builder.setMaxValues(value)
}

/** See [AttachmentUpload.Builder.build] */
fun build(): AttachmentUpload {
return builder.build()
}
}

/**
* Discord text input, see [AttachmentUpload][net.dv8tion.jda.api.components.attachmentupload.AttachmentUpload].
*
* @param customId The custom ID of the input, see [AttachmentUpload.Builder.setCustomId]
* @param uniqueId Unique identifier of this component, see [Component.withUniqueId]
* @param required Whether the user must upload files, see [AttachmentUpload.Builder.setRequired]
* @param range Minimum and maximum amount of files a user can send, see [AttachmentUpload.Builder.setRequiredRange]
* @param block Lambda allowing further configuration
*/
inline fun AttachmentUpload(
customId: String,
uniqueId: Int = -1,
required: Boolean = true,
range: IntRange? = null,
block: InlineAttachmentUpload.() -> Unit = {},
): AttachmentUpload {
return AttachmentUpload.create(customId)
.let(::InlineAttachmentUpload)
.apply {
if (uniqueId != -1)
this.uniqueId = uniqueId
if (!required)
this.required = false
if (range != null)
this.range = range
block()
}
.build()
}

/**
* Sets the minimum and maximum amount of files a user can send, see [AttachmentUpload.Builder.setRequiredRange].
*/
fun AttachmentUpload.Builder.setRequiredRange(range: IntRange) = setRequiredRange(range.first, range.last)
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
repositories {
mavenCentral()
mavenLocal()
maven("https://jitpack.io")
}
4 changes: 2 additions & 2 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ h2 = "2.3.232"
hikaricp = "6.2.1"
jackson = "2.20.0"
java-string-similarity = "2.0.0"
jda = "6.0.0-rc.5"
jda = "ad5fc4f85d"
jda-emojis = "3.0.0"
jda-ktx = "0.12.0"
jemoji = "1.7.4"
Expand Down Expand Up @@ -55,7 +55,7 @@ jackson-databind = { module = "com.fasterxml.jackson.core:jackson-databind", ver
jackson-dataformat-yaml = { module = "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml", version.ref = "jackson" }
jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson" }
java-string-similarity = { module = "info.debatty:java-string-similarity", version.ref = "java-string-similarity" }
jda = { module = "net.dv8tion:JDA", version.ref = "jda" }
jda = { module = "io.github.freya022:JDA", version.ref = "jda" }
jda-emojis = { module = "dev.freya02:jda-emojis", version.ref = "jda-emojis" }
jda-ktx = { module = "club.minnced:jda-ktx", version.ref = "jda-ktx" }
jemoji = { module = "net.fellbaum:jemoji", version.ref = "jemoji" }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package dev.freya02.botcommands.bot.commands.slash

import dev.freya02.botcommands.bot.CustomObject
import dev.freya02.botcommands.jda.ktx.components.AttachmentUpload
import dev.freya02.botcommands.jda.ktx.components.EntitySelectMenu
import dev.freya02.botcommands.jda.ktx.components.StringSelectMenu
import dev.freya02.botcommands.jda.ktx.components.TextInput
import dev.freya02.botcommands.jda.ktx.components.row
import dev.freya02.botcommands.jda.ktx.messages.reply_
import dev.freya02.botcommands.jda.ktx.messages.send
Expand All @@ -25,8 +25,8 @@ import io.github.freya022.botcommands.api.modals.annotations.ModalInput
import io.github.freya022.botcommands.api.modals.annotations.RequiresModals
import io.github.freya022.botcommands.api.modals.create
import net.dv8tion.jda.api.components.selections.EntitySelectMenu.SelectTarget
import net.dv8tion.jda.api.components.textinput.TextInputStyle
import net.dv8tion.jda.api.entities.IMentionable
import net.dv8tion.jda.api.entities.Message
import net.dv8tion.jda.api.entities.channel.ChannelType
import net.dv8tion.jda.api.entities.channel.middleman.GuildChannel
import net.dv8tion.jda.api.interactions.IntegrationType
Expand All @@ -37,6 +37,7 @@ private const val SLASH_MODAL_TEXT_INPUT = "SlashModal: textInput"
private const val SLASH_MODAL_STRING_SELECT_INPUT = "SlashModal: stringSelect"
private const val SLASH_MODAL_ENTITY_SELECT_INPUT = "SlashModal: entitySelect"
private const val SLASH_MODAL_CHANNEL_SELECT_INPUT = "SlashModal: channelSelect"
private const val SLASH_MODAL_ATTACHMENT_INPUT = "SlashModal: attachment"

@Command
@RequiresModals
Expand All @@ -47,9 +48,9 @@ class SlashModal(private val buttons: Buttons) : ApplicationCommand(), GlobalApp
val modal = modals.create("Title") {
text("This is a text display")

label("Sample text") {
child = TextInput(SLASH_MODAL_TEXT_INPUT, TextInputStyle.SHORT)
}
// label("Sample text") {
// child = TextInput(SLASH_MODAL_TEXT_INPUT, TextInputStyle.SHORT)
// }

label("String select menu") {
child = StringSelectMenu(SLASH_MODAL_STRING_SELECT_INPUT, required = false) {
Expand All @@ -71,6 +72,14 @@ class SlashModal(private val buttons: Buttons) : ApplicationCommand(), GlobalApp
)
}

label("Attachment") {
child = AttachmentUpload(
SLASH_MODAL_ATTACHMENT_INPUT,
range = 1..2,
required = false
)
}

bindTo(SLASH_MODAL_MODAL_HANDLER, "User data", 420, null)

// bindTo { event -> onModalSubmitted(event, "User data", 420, event.values[0].asString, CustomObject()) }
Expand All @@ -91,10 +100,11 @@ class SlashModal(private val buttons: Buttons) : ApplicationCommand(), GlobalApp
suspend fun onModalSubmitted(
event: ModalEvent,
@ModalData dataStr: String,
@ModalInput(customId = SLASH_MODAL_TEXT_INPUT) inputStr: String,
// @ModalInput(customId = SLASH_MODAL_TEXT_INPUT) inputStr: String,
@ModalInput(customId = SLASH_MODAL_STRING_SELECT_INPUT) selectedStrings: List<String>,
@ModalInput(customId = SLASH_MODAL_ENTITY_SELECT_INPUT) selectedEntities: List<IMentionable>,
@ModalInput(customId = SLASH_MODAL_CHANNEL_SELECT_INPUT) selectedChannels: List<GuildChannel>,
@ModalInput(customId = SLASH_MODAL_ATTACHMENT_INPUT) attachments: List<Message.Attachment>,
@ModalData dataInt: Int,
@ModalData definitelyNull: Any?,
customObject: CustomObject
Expand All @@ -104,10 +114,10 @@ class SlashModal(private val buttons: Buttons) : ApplicationCommand(), GlobalApp
Submitted:
dataStr: $dataStr
dataInt: $dataInt
inputStr: $inputStr
selectedStrings: $selectedStrings
selectedEntities: $selectedEntities
selectedChannels: $selectedChannels
attachments: $attachments
definitelyNull: $definitelyNull
customObject: $customObject
""".trimIndent(),
Expand Down