-
Notifications
You must be signed in to change notification settings - Fork 82
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MessageBuilder is the new common supertype of MessageCreateBuilder and MessageModifyBuilder. The support for attachments was improved by adding AttachmentBuilder, which can be configured when adding files to messages. The way multipart requests are sent is now also more closely aligned with the documentation [1]. [1] https://discord.com/developers/docs/reference#uploading-files
- Loading branch information
1 parent
f8d4333
commit 6c69060
Showing
27 changed files
with
856 additions
and
852 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
28 changes: 28 additions & 0 deletions
28
rest/src/commonMain/kotlin/builder/message/AttachmentBuilder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package dev.kord.rest.builder.message | ||
|
||
import dev.kord.common.annotation.KordDsl | ||
import dev.kord.common.entity.Snowflake | ||
import dev.kord.common.entity.optional.Optional | ||
import dev.kord.common.entity.optional.delegate.delegate | ||
import dev.kord.rest.builder.RequestBuilder | ||
import dev.kord.rest.json.request.AttachmentRequest | ||
|
||
@KordDsl | ||
public class AttachmentBuilder(private val id: Snowflake) : RequestBuilder<AttachmentRequest> { | ||
|
||
private var _filename: Optional<String> = Optional.Missing() | ||
|
||
/** The name of the attached file. */ | ||
public var filename: String? by ::_filename.delegate() | ||
|
||
private var _description: Optional<String> = Optional.Missing() | ||
|
||
/** The description for the file (max 1024 characters). */ | ||
public var description: String? by ::_description.delegate() | ||
|
||
override fun toRequest(): AttachmentRequest = AttachmentRequest( | ||
id = id, | ||
filename = _filename, | ||
description = _description, | ||
) | ||
} |
147 changes: 147 additions & 0 deletions
147
rest/src/commonMain/kotlin/builder/message/MessageBuilder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package dev.kord.rest.builder.message | ||
|
||
import dev.kord.common.annotation.KordDsl | ||
import dev.kord.common.entity.MessageFlag | ||
import dev.kord.common.entity.MessageFlags | ||
import dev.kord.common.entity.Snowflake | ||
import dev.kord.common.entity.optional.Optional | ||
import dev.kord.rest.NamedFile | ||
import dev.kord.rest.builder.component.ActionRowBuilder | ||
import dev.kord.rest.builder.component.MessageComponentBuilder | ||
import dev.kord.rest.request.MultipartRequest | ||
import io.ktor.client.request.forms.* | ||
import kotlin.contracts.InvocationKind.EXACTLY_ONCE | ||
import kotlin.contracts.contract | ||
|
||
@KordDsl | ||
public interface MessageBuilder { | ||
|
||
/** The message contents (up to 2000 characters). */ | ||
public var content: String? | ||
|
||
/** Up to 10 embeds (up to 6000 characters). */ | ||
public var embeds: MutableList<EmbedBuilder>? | ||
|
||
/** | ||
* The mentions in the message that are allowed to trigger a ping. | ||
* | ||
* Setting this to `null` will default to triggering pings for all mentions. | ||
*/ | ||
public var allowedMentions: AllowedMentionsBuilder? | ||
|
||
/** The components to include with the message.*/ | ||
public var components: MutableList<MessageComponentBuilder>? | ||
|
||
/** The files to include as attachments. */ | ||
public val files: MutableList<NamedFile> | ||
|
||
/** | ||
* The attachment objects with [filename][AttachmentBuilder.filename] and | ||
* [description][AttachmentBuilder.description]. | ||
*/ | ||
public var attachments: MutableList<AttachmentBuilder>? | ||
|
||
/** | ||
* Optional custom [MessageFlags]. | ||
* | ||
* @see suppressEmbeds | ||
*/ | ||
public var flags: MessageFlags? | ||
|
||
/** Do not include any embeds when serializing this message. */ | ||
public var suppressEmbeds: Boolean? | ||
|
||
/** Adds a [file][NamedFile] with [name] and [contentProvider] to [files]. */ | ||
public fun addFile(name: String, contentProvider: ChannelProvider): NamedFile { | ||
val file = NamedFile(name, contentProvider) | ||
files.add(file) | ||
return file | ||
} | ||
} | ||
|
||
/** | ||
* Adds an [embed][EmbedBuilder] configured by [builder] to the [embeds][MessageBuilder.embeds] of the message. | ||
* | ||
* A message can have up to 10 embeds. | ||
*/ | ||
public inline fun MessageBuilder.embed(builder: EmbedBuilder.() -> Unit) { | ||
contract { callsInPlace(builder, EXACTLY_ONCE) } | ||
val embed = EmbedBuilder().apply(builder) | ||
embeds?.add(embed) ?: run { embeds = mutableListOf(embed) } | ||
} | ||
|
||
/** | ||
* Configures the mentions in the message that are allowed to trigger a ping. | ||
* | ||
* Not calling this function will result in the default behavior (ping for all mentions), calling this function but not | ||
* configuring it before the request is build will result in all mentions being ignored. | ||
*/ | ||
public inline fun MessageBuilder.allowedMentions(builder: AllowedMentionsBuilder.() -> Unit = {}) { | ||
contract { callsInPlace(builder, EXACTLY_ONCE) } | ||
val mentions = allowedMentions ?: (AllowedMentionsBuilder().also { allowedMentions = it }) | ||
mentions.builder() | ||
} | ||
|
||
/** | ||
* Adds an [action row][ActionRowBuilder] configured by the [builder] to the [components][MessageBuilder.components] of | ||
* the message. | ||
* | ||
* A message can have up to five action rows. | ||
*/ | ||
public inline fun MessageBuilder.actionRow(builder: ActionRowBuilder.() -> Unit) { | ||
contract { callsInPlace(builder, EXACTLY_ONCE) } | ||
val actionRow = ActionRowBuilder().apply(builder) | ||
components?.add(actionRow) ?: run { components = mutableListOf(actionRow) } | ||
} | ||
|
||
/** | ||
* Adds a [file][NamedFile] with [name] and [contentProvider] to [files][MessageBuilder.files]. | ||
* | ||
* The corresponding attachment object can be configured with [builder]. | ||
*/ | ||
public inline fun MessageBuilder.addFile( | ||
name: String, | ||
contentProvider: ChannelProvider, | ||
builder: AttachmentBuilder.() -> Unit, | ||
): NamedFile { | ||
contract { callsInPlace(builder, EXACTLY_ONCE) } | ||
// see https://discord.com/developers/docs/reference#uploading-files: | ||
// we use the index of a file in the `files` list as `n` in `files[n]`, as implemented in `MultipartRequest.data` | ||
/** (clickable link: [MultipartRequest.data]) */ | ||
val file = NamedFile(name, contentProvider) | ||
files.add(file) | ||
val index = files.lastIndex | ||
val attachment = AttachmentBuilder(id = Snowflake(index.toLong())).apply(builder) | ||
attachments?.add(attachment) ?: run { attachments = mutableListOf(attachment) } | ||
return file | ||
} | ||
|
||
/** Sets the [flags][MessageBuilder.flags] for the message. */ | ||
public inline fun MessageBuilder.messageFlags(builder: MessageFlags.Builder.() -> Unit) { | ||
contract { callsInPlace(builder, EXACTLY_ONCE) } | ||
flags = MessageFlags(builder) | ||
} | ||
|
||
|
||
internal fun buildMessageFlags( | ||
base: MessageFlags?, | ||
suppressEmbeds: Boolean?, | ||
suppressNotifications: Boolean? = null, | ||
ephemeral: Boolean? = null, | ||
): Optional<MessageFlags> = | ||
if (base == null && suppressEmbeds == null && suppressNotifications == null && ephemeral == null) { | ||
Optional.Missing() | ||
} else { | ||
val flags = MessageFlags { | ||
if (base != null) +base | ||
fun apply(add: Boolean?, flag: MessageFlag) = when (add) { | ||
true -> +flag | ||
false -> -flag | ||
null -> {} | ||
} | ||
apply(suppressEmbeds, MessageFlag.SuppressEmbeds) | ||
apply(suppressNotifications, MessageFlag.SuppressNotifications) | ||
apply(ephemeral, MessageFlag.Ephemeral) | ||
} | ||
Optional.Value(flags) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 25 additions & 36 deletions
61
rest/src/commonMain/kotlin/builder/message/create/ForumMessageCreateBuilder.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,55 +1,44 @@ | ||
package dev.kord.rest.builder.message.create | ||
|
||
import dev.kord.common.annotation.KordDsl | ||
import dev.kord.common.entity.MessageFlags | ||
import dev.kord.common.entity.Snowflake | ||
import dev.kord.common.entity.optional.Optional | ||
import dev.kord.common.entity.optional.coerceToMissing | ||
import dev.kord.common.entity.optional.delegate.delegate | ||
import dev.kord.common.entity.optional.map | ||
import dev.kord.common.entity.optional.mapCopy | ||
import dev.kord.common.entity.optional.mapList | ||
import dev.kord.rest.NamedFile | ||
import dev.kord.rest.builder.RequestBuilder | ||
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.builder.message.buildMessageFlags | ||
import dev.kord.rest.json.request.ForumThreadMessageRequest | ||
import dev.kord.rest.json.request.MultipartForumThreadMessageCreateRequest | ||
|
||
@KordDsl | ||
public class ForumMessageCreateBuilder : MessageCreateBuilder, | ||
public class ForumMessageCreateBuilder : | ||
AbstractMessageCreateBuilder(), | ||
RequestBuilder<MultipartForumThreadMessageCreateRequest> { | ||
|
||
override var content: String? = null | ||
|
||
override var tts: Boolean? = null | ||
|
||
override val embeds: MutableList<EmbedBuilder> = mutableListOf() | ||
|
||
override var allowedMentions: AllowedMentionsBuilder? = null | ||
|
||
override val components: MutableList<MessageComponentBuilder> = mutableListOf() | ||
|
||
override val files: MutableList<NamedFile> = mutableListOf() | ||
// see https://discord.com/developers/docs/resources/channel#start-thread-in-forum-or-media-channel | ||
|
||
private var _stickerIds: Optional<MutableList<Snowflake>> = Optional.Missing() | ||
public val stickerIds: MutableList<Snowflake>? by ::_stickerIds.delegate() | ||
|
||
override var flags: MessageFlags? = null | ||
override var suppressEmbeds: Boolean? = null | ||
override var suppressNotifications: Boolean? = null | ||
/** The IDs of up to three stickers to send in the message. */ | ||
public var stickerIds: MutableList<Snowflake>? by ::_stickerIds.delegate() | ||
|
||
override fun toRequest(): MultipartForumThreadMessageCreateRequest = MultipartForumThreadMessageCreateRequest( | ||
request = ForumThreadMessageRequest( | ||
content = _content, | ||
tts = _tts, | ||
embeds = _embeds.mapList { it.toRequest() }, | ||
allowedMentions = _allowedMentions.map { it.build() }, | ||
components = _components.mapList { it.build() }, | ||
stickerIds = _stickerIds.mapCopy(), | ||
attachments = _attachments.mapList { it.toRequest() }, | ||
flags = buildMessageFlags(flags, suppressEmbeds, suppressNotifications), | ||
), | ||
files = files.toList(), | ||
) | ||
} | ||
|
||
override fun toRequest(): MultipartForumThreadMessageCreateRequest { | ||
return MultipartForumThreadMessageCreateRequest( | ||
ForumThreadMessageRequest( | ||
content = Optional(content).coerceToMissing(), | ||
embeds = Optional(embeds).mapList { it.toRequest() }, | ||
allowedMentions = Optional(allowedMentions).coerceToMissing().map { it.build() }, | ||
components = Optional(components).coerceToMissing().mapList { it.build() }, | ||
stickerIds = _stickerIds, | ||
flags = buildMessageFlags(flags, suppressEmbeds, suppressNotifications), | ||
), | ||
files | ||
) | ||
} | ||
/** Add a [stickerId] to [stickerIds][ForumMessageCreateBuilder.stickerIds]. */ | ||
public fun ForumMessageCreateBuilder.stickerId(stickerId: Snowflake) { | ||
stickerIds?.add(stickerId) ?: run { stickerIds = mutableListOf(stickerId) } | ||
} |
Oops, something went wrong.