diff --git a/core/src/main/kotlin/behavior/MessageBehavior.kt b/core/src/main/kotlin/behavior/MessageBehavior.kt index 68dbf5bfcc1..7da744643b9 100644 --- a/core/src/main/kotlin/behavior/MessageBehavior.kt +++ b/core/src/main/kotlin/behavior/MessageBehavior.kt @@ -17,6 +17,7 @@ import dev.kord.core.supplier.getChannelOf import dev.kord.core.supplier.getChannelOfOrNull import dev.kord.rest.builder.message.MessageCreateBuilder import dev.kord.rest.builder.message.MessageModifyBuilder +import dev.kord.rest.builder.webhook.EditWebhookMessageBuilder import dev.kord.rest.request.RestRequestException import dev.kord.rest.service.RestClient import kotlinx.coroutines.flow.Flow @@ -217,13 +218,46 @@ fun MessageBehavior( * @return The edited [Message]. * * @throws [RestRequestException] if something went wrong during the request. + * @see editWebhookMessage */ @OptIn(ExperimentalContracts::class) suspend inline fun MessageBehavior.edit(builder: MessageModifyBuilder.() -> Unit): Message { contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) } - val response = kord.rest.channel.editMessage(channelId = channelId, messageId = id, builder = builder) + + val response = + kord.rest.channel.editMessage(channelId = channelId, messageId = id, builder = builder) + val data = MessageData.from(response) + + return Message(data, kord) +} + +/** + * Requests to edit this message. + * + * @return The edited [Message]. + * + * @throws [RestRequestException] if something went wrong during the request. + * @see edit + */ +@OptIn(ExperimentalContracts::class) +suspend inline fun MessageBehavior.editWebhookMessage( + webhookId: Snowflake, + token: String, + builder: EditWebhookMessageBuilder.() -> Unit +): Message { + contract { + callsInPlace(builder, InvocationKind.EXACTLY_ONCE) + } + + val response = + kord.rest.webhook.editWebhookMessage( + webhookId = webhookId, + messageId = id, + token = token, + builder = builder + ) val data = MessageData.from(response) return Message(data, kord) diff --git a/core/src/main/kotlin/entity/channel/MessageChannel.kt b/core/src/main/kotlin/entity/channel/MessageChannel.kt index d59f24c7eff..4e69db7179b 100644 --- a/core/src/main/kotlin/entity/channel/MessageChannel.kt +++ b/core/src/main/kotlin/entity/channel/MessageChannel.kt @@ -8,7 +8,6 @@ import dev.kord.core.behavior.channel.MessageChannelBehavior import dev.kord.core.entity.Message import dev.kord.core.supplier.EntitySupplyStrategy import dev.kord.core.toInstant -import dev.kord.core.toSnowflakeOrNull import java.time.Instant /** diff --git a/core/src/test/kotlin/rest/RestTest.kt b/core/src/test/kotlin/rest/RestTest.kt index b26bb7cc3f4..31ffe02f15f 100644 --- a/core/src/test/kotlin/rest/RestTest.kt +++ b/core/src/test/kotlin/rest/RestTest.kt @@ -366,6 +366,14 @@ class RestServiceTest { content = "hello world!" } + val message = webhook.execute(webhook.token!!) { + content = "a" + } + + message.editWebhookMessage(webhook.id, webhook.token!!) { + content = "b" + } + webhook.delete(reason = "test") Unit } @@ -438,16 +446,16 @@ class RestServiceTest { val textChannel = guild.createTextChannel("move me to a category") guild.swapChannelPositions { - move(textChannel.id){ parentId = category.id } + move(textChannel.id) { parentId = category.id } } val currentTextChannel = guild.getChannelOf(textChannel.id) - assertEquals(category.id,currentTextChannel.categoryId) + assertEquals(category.id, currentTextChannel.categoryId) } @OptIn(KordPreview::class) fun `guild application commands`(): Unit = runBlocking { - val command = guild.createApplicationCommand("test", "automated test"){ + val command = guild.createApplicationCommand("test", "automated test") { group("test-group", "automated test") { subCommand("test-sub-command", "automated test") { int("integer", "test choice") { diff --git a/rest/src/main/kotlin/builder/webhook/EditWebhookMessageBuilder.kt b/rest/src/main/kotlin/builder/webhook/EditWebhookMessageBuilder.kt new file mode 100644 index 00000000000..0cbdcd13e40 --- /dev/null +++ b/rest/src/main/kotlin/builder/webhook/EditWebhookMessageBuilder.kt @@ -0,0 +1,34 @@ +package dev.kord.rest.builder.webhook + +import dev.kord.common.entity.AllowedMentions +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.builder.message.EmbedBuilder +import dev.kord.rest.json.request.WebhookEditMessageRequest +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract + +class EditWebhookMessageBuilder : RequestBuilder { + + private var _content: Optional = Optional.Missing() + var content: String? by ::_content.delegate() + + var embeds: MutableList = mutableListOf() + + private var _allowedMentions: Optional = Optional.Missing() + var allowedMentions: AllowedMentions? by ::_allowedMentions.delegate() + + @OptIn(ExperimentalContracts::class) + inline fun embed(builder: EmbedBuilder.() -> Unit) { + contract { + callsInPlace(builder, InvocationKind.EXACTLY_ONCE) + } + embeds.add(EmbedBuilder().apply(builder)) + } + + override fun toRequest(): WebhookEditMessageRequest = WebhookEditMessageRequest( + _content, Optional.missingOnEmpty(embeds.map(EmbedBuilder::toRequest)), _allowedMentions + ) +} diff --git a/rest/src/main/kotlin/json/request/MessageRequests.kt b/rest/src/main/kotlin/json/request/MessageRequests.kt index efdd8f7fdf1..3016a506fa8 100644 --- a/rest/src/main/kotlin/json/request/MessageRequests.kt +++ b/rest/src/main/kotlin/json/request/MessageRequests.kt @@ -80,7 +80,7 @@ data class EmbedFieldRequest( data class MessageEditPatchRequest( val content: Optional = Optional.Missing(), val embed: Optional = Optional.Missing(), - val flags: Optional = Optional.Missing(), + val flags: Optional = Optional.Missing(), @SerialName("allowed_mentions") val allowedMentions: Optional = Optional.Missing(), ) diff --git a/rest/src/main/kotlin/json/request/WebhookRequests.kt b/rest/src/main/kotlin/json/request/WebhookRequests.kt index 6295d78dc5f..53117036457 100644 --- a/rest/src/main/kotlin/json/request/WebhookRequests.kt +++ b/rest/src/main/kotlin/json/request/WebhookRequests.kt @@ -32,4 +32,11 @@ data class WebhookExecuteRequest( data class MultiPartWebhookExecuteRequest( val request: WebhookExecuteRequest, val file: Pair? -) \ No newline at end of file +) + +@Serializable +data class WebhookEditMessageRequest( + val content: Optional = Optional.Missing(), + val embeds: Optional> = Optional.Missing(), + val allowedMentions: Optional = Optional.Missing() +) diff --git a/rest/src/main/kotlin/route/Route.kt b/rest/src/main/kotlin/route/Route.kt index 9d7ecbe1030..7822347d78b 100644 --- a/rest/src/main/kotlin/route/Route.kt +++ b/rest/src/main/kotlin/route/Route.kt @@ -5,7 +5,6 @@ import dev.kord.common.annotation.KordExperimental import dev.kord.common.annotation.KordPreview import dev.kord.common.entity.* import dev.kord.rest.json.optional -import dev.kord.rest.json.request.MessageEditPatchRequest import dev.kord.rest.json.response.* import io.ktor.http.* import kotlinx.serialization.DeserializationStrategy @@ -427,6 +426,12 @@ sealed class Route( object ExecuteGithubWebhookPost : Route(HttpMethod.Post, "/webhooks/$WebhookId/$WebhookToken", NoStrategy) + object EditWebhookMessage : Route( + HttpMethod.Patch, + "/webhooks/$WebhookId/$WebhookToken/messages/$MessageId", + DiscordMessage.serializer() + ) + object VoiceRegionsGet : Route>( HttpMethod.Get, diff --git a/rest/src/main/kotlin/service/WebhookService.kt b/rest/src/main/kotlin/service/WebhookService.kt index 472e883b6ba..3487961f743 100644 --- a/rest/src/main/kotlin/service/WebhookService.kt +++ b/rest/src/main/kotlin/service/WebhookService.kt @@ -4,10 +4,12 @@ import dev.kord.common.annotation.KordExperimental import dev.kord.common.entity.DiscordMessage import dev.kord.common.entity.DiscordWebhook import dev.kord.common.entity.Snowflake +import dev.kord.rest.builder.webhook.EditWebhookMessageBuilder import dev.kord.rest.builder.webhook.ExecuteWebhookBuilder import dev.kord.rest.builder.webhook.WebhookCreateBuilder import dev.kord.rest.builder.webhook.WebhookModifyBuilder import dev.kord.rest.json.request.WebhookCreateRequest +import dev.kord.rest.json.request.WebhookEditMessageRequest import dev.kord.rest.json.request.WebhookExecuteRequest import dev.kord.rest.json.request.WebhookModifyRequest import dev.kord.rest.request.RequestHandler @@ -137,4 +139,25 @@ class WebhookService(requestHandler: RequestHandler) : RestService(requestHandle parameter("wait", "$wait") body(JsonObject.serializer(), body) } + + @OptIn(ExperimentalContracts::class) + suspend inline fun editWebhookMessage( + webhookId: Snowflake, + token: String, + messageId: Snowflake, + builder: EditWebhookMessageBuilder.() -> Unit + ): DiscordMessage { + contract { + callsInPlace(builder, InvocationKind.EXACTLY_ONCE) + } + + return call(Route.EditWebhookMessage) { + + keys[Route.WebhookId] = webhookId + keys[Route.WebhookToken] = token + keys[Route.MessageId] = messageId + val body = EditWebhookMessageBuilder().apply(builder).toRequest() + body(WebhookEditMessageRequest.serializer(), body) + } + } } \ No newline at end of file