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

interaction code cleanup #312

Merged
merged 4 commits into from
Jun 13, 2021
Merged
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 @@ -50,7 +50,7 @@ suspend inline fun EphemeralInteractionResponseBehavior.followUp(
builder: EphemeralFollowupMessageCreateBuilder.() -> Unit = {}
): EphemeralFollowupMessage {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val builder = EphemeralFollowupMessageCreateBuilder(content).apply(builder)
val builder = EphemeralFollowupMessageCreateBuilder().apply(builder)
val response = kord.rest.interaction.createFollowupMessage(applicationId, token, builder.toRequest())
val message = Message(response.toData(), kord)
return EphemeralFollowupMessage(message, applicationId, token, kord)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -132,10 +132,7 @@ suspend inline fun InteractionBehavior.respondEphemeral(
): EphemeralInteractionResponseBehavior {

contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val builder = EphemeralInteractionResponseCreateBuilder().apply {
this.content = content
builder()
}
val builder = EphemeralInteractionResponseCreateBuilder().apply(builder)
val request = builder.toRequest()
kord.rest.interaction.createInteractionResponse(id, token, request)
return EphemeralInteractionResponseBehavior(applicationId, token, kord)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ sealed class InteractionFollowup(val message: Message) : FollowupMessageBehavior
* @param message The message created by this follow-up.
* To use the message behavior your application must be authorized as a bot.
*/
@KordPreview
class PublicFollowupMessage(
message: Message,
override val applicationId: Snowflake,
Expand All @@ -65,6 +66,7 @@ class PublicFollowupMessage(
* Note: Any rest calls made through the [message] object e.g: `message.delete()` will throw since the message
* is deleted once the client receives it.
*/
@KordPreview
class EphemeralFollowupMessage(
message: Message,
override val applicationId: Snowflake,
Expand Down
1 change: 1 addition & 0 deletions rest/src/main/kotlin/builder/interaction/Base.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import kotlin.contracts.InvocationKind
import kotlin.contracts.contract

sealed interface BaseInteractionResponseBuilder<T> : RequestBuilder<T> {

var content: String?

val embeds: MutableList<EmbedBuilder>
Expand Down
212 changes: 82 additions & 130 deletions rest/src/main/kotlin/builder/interaction/FollowupMessageBuilders.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,12 @@ import dev.kord.common.entity.optional.Optional
import dev.kord.common.entity.optional.OptionalBoolean
import dev.kord.common.entity.optional.delegate.delegate
import dev.kord.common.entity.optional.map
import dev.kord.common.entity.optional.mapList
import dev.kord.rest.builder.RequestBuilder
import dev.kord.rest.builder.component.ActionRowBuilder
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.json.request.EmbedRequest
import dev.kord.rest.json.request.FollowupMessageCreateRequest
import dev.kord.rest.json.request.FollowupMessageModifyRequest
import dev.kord.rest.json.request.MultipartFollowupMessageCreateRequest
import dev.kord.rest.json.request.MultipartFollowupMessageModifyRequest
import dev.kord.rest.json.request.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.InputStream
Expand All @@ -26,41 +21,70 @@ import kotlin.contracts.ExperimentalContracts
import kotlin.contracts.InvocationKind
import kotlin.contracts.contract


sealed interface FollowupMessageBuilder<T> : RequestBuilder<T> {

var tts: Boolean?

var allowedMentions: AllowedMentionsBuilder?

val embeds: MutableList<EmbedBuilder>

val components: MutableList<MessageComponentBuilder>

val content: String?

}

@OptIn(ExperimentalContracts::class)
@KordPreview
inline fun <T> FollowupMessageBuilder<T>.actionRow(builder: ActionRowBuilder.() -> Unit) {
contract {
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
}

components.add(ActionRowBuilder().apply(builder))
}

@OptIn(ExperimentalContracts::class)
inline fun <T> FollowupMessageBuilder<T>.embed(builder: EmbedBuilder.() -> Unit) {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
embeds += EmbedBuilder().apply(builder)
}

/**
* Configures the mentions that should trigger a mention (aka ping). Not calling this function will result in the default behavior
* (ping everything), calling this function but not configuring it before the request is build will result in all
* pings being ignored.
*/
@OptIn(ExperimentalContracts::class)
inline fun <T> FollowupMessageBuilder<T>.allowedMentions(block: AllowedMentionsBuilder.() -> Unit = {}) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
allowedMentions = (allowedMentions ?: AllowedMentionsBuilder()).apply(block)
}



@KordPreview
@KordDsl
class PublicFollowupMessageModifyBuilder :
RequestBuilder<MultipartFollowupMessageModifyRequest> {
FollowupMessageBuilder<MultipartFollowupMessageModifyRequest> {
private var _content: Optional<String> = Optional.Missing()
var content: String? by ::_content.delegate()
override var content: String? by ::_content.delegate()

override val embeds: MutableList<EmbedBuilder> = mutableListOf()

private var _embeds: Optional<MutableList<EmbedBuilder>> = Optional.Missing()
var embeds: MutableList<EmbedBuilder>? by ::_embeds.delegate()
private var _tts: OptionalBoolean = OptionalBoolean.Missing
override var tts: Boolean? by ::_tts.delegate()

val files: MutableList<Pair<String, InputStream>> = mutableListOf()


private var _allowedMentions: Optional<AllowedMentionsBuilder> = Optional.Missing()
var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()
override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()

@KordPreview
val components: MutableList<MessageComponentBuilder> = mutableListOf()

@OptIn(ExperimentalContracts::class)
inline fun embed(builder: EmbedBuilder.() -> Unit) {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
if (embeds == null) embeds = mutableListOf()
embeds!! += EmbedBuilder().apply(builder)
}

@OptIn(ExperimentalContracts::class)
@KordPreview
inline fun actionRow(builder: ActionRowBuilder.() -> Unit) {
contract {
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
}

components.add(ActionRowBuilder().apply(builder))
}
override val components: MutableList<MessageComponentBuilder> = mutableListOf()


fun addFile(name: String, content: InputStream) {
Expand All @@ -70,24 +94,11 @@ class PublicFollowupMessageModifyBuilder :
suspend fun addFile(path: Path) = withContext(Dispatchers.IO) {
addFile(path.fileName.toString(), Files.newInputStream(path))
}

/**
* Configures the mentions that should trigger a mention (aka ping). Not calling this function will result in the default behavior
* (ping everything), calling this function but not configuring it before the request is build will result in all
* pings being ignored.
*/
@OptIn(ExperimentalContracts::class)
inline fun allowedMentions(block: AllowedMentionsBuilder.() -> Unit = {}) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
allowedMentions = (allowedMentions ?: AllowedMentionsBuilder()).apply(block)
}


override fun toRequest(): MultipartFollowupMessageModifyRequest {
return MultipartFollowupMessageModifyRequest(
FollowupMessageModifyRequest(
_content,
_embeds.mapList { it.toRequest() },
Optional.missingOnEmpty(embeds.map(EmbedBuilder::toRequest)),
_allowedMentions.map { it.build() },
Optional.missingOnEmpty(components.map(MessageComponentBuilder::build))
),
Expand All @@ -100,29 +111,19 @@ class PublicFollowupMessageModifyBuilder :
@KordPreview
@KordDsl
class EphemeralFollowupMessageModifyBuilder :
RequestBuilder<FollowupMessageModifyRequest> {
FollowupMessageBuilder<FollowupMessageModifyRequest> {
private var _content: Optional<String> = Optional.Missing()
var content: String? by ::_content.delegate()
override var content: String? by ::_content.delegate()

private var _embeds: Optional<MutableList<EmbedBuilder>> = Optional.Missing()
var embeds: MutableList<EmbedBuilder>? by ::_embeds.delegate()

private var _allowedMentions: Optional<AllowedMentionsBuilder> = Optional.Missing()
var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()
private var _tts: OptionalBoolean = OptionalBoolean.Missing
override var tts: Boolean? by ::_tts.delegate()

val components: MutableList<MessageComponentBuilder> = mutableListOf()
override val embeds: MutableList<EmbedBuilder> = mutableListOf()

private var _allowedMentions: Optional<AllowedMentionsBuilder> = Optional.Missing()
override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()

/**
* Configures the mentions that should trigger a mention (aka ping). Not calling this function will result in the default behavior
* (ping everything), calling this function but not configuring it before the request is build will result in all
* pings being ignored.
*/
@OptIn(ExperimentalContracts::class)
inline fun allowedMentions(block: AllowedMentionsBuilder.() -> Unit = {}) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
allowedMentions = (allowedMentions ?: AllowedMentionsBuilder()).apply(block)
}
override val components: MutableList<MessageComponentBuilder> = mutableListOf()

override fun toRequest(): FollowupMessageModifyRequest {
return FollowupMessageModifyRequest(
Expand All @@ -136,66 +137,31 @@ class EphemeralFollowupMessageModifyBuilder :

@KordPreview
@KordDsl
class PublicFollowupMessageCreateBuilder : RequestBuilder<MultipartFollowupMessageCreateRequest> {
class PublicFollowupMessageCreateBuilder : FollowupMessageBuilder<MultipartFollowupMessageCreateRequest> {

private var _content: Optional<String> = Optional.Missing()
var content: String? by ::_content.delegate()
override var content: String? by ::_content.delegate()


private var _tts: OptionalBoolean = OptionalBoolean.Missing
var tts: Boolean? by ::_tts.delegate()
override var tts: Boolean? by ::_tts.delegate()

private var _allowedMentions: Optional<AllowedMentionsBuilder> = Optional.Missing()
var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()
override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()

val files: MutableList<Pair<String, InputStream>> = mutableListOf()
var embeds: MutableList<EmbedRequest> = mutableListOf()

val components: MutableList<MessageComponentBuilder> = mutableListOf()

fun addFile(name: String, content: InputStream) {
files += name to content
}

suspend fun addFile(path: Path) = withContext(Dispatchers.IO) {
addFile(path.fileName.toString(), Files.newInputStream(path))
}

/**
* Configures the mentions that should trigger a mention (aka ping). Not calling this function will result in the default behavior
* (ping everything), calling this function but not configuring it before the request is build will result in all
* pings being ignored.
*/
@OptIn(ExperimentalContracts::class)
inline fun allowedMentions(block: AllowedMentionsBuilder.() -> Unit = {}) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
allowedMentions = (allowedMentions ?: AllowedMentionsBuilder()).apply(block)
}
override val embeds: MutableList<EmbedBuilder> = mutableListOf()

@OptIn(ExperimentalContracts::class)
@KordPreview
inline fun actionRow(builder: ActionRowBuilder.() -> Unit) {
contract {
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
}
override val components: MutableList<MessageComponentBuilder> = mutableListOf()

components.add(ActionRowBuilder().apply(builder))
}

@OptIn(ExperimentalContracts::class)
inline fun embed(builder: EmbedBuilder.() -> Unit) {
contract {
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
}
embeds.add(EmbedBuilder().apply(builder).toRequest())
}

override fun toRequest(): MultipartFollowupMessageCreateRequest =
MultipartFollowupMessageCreateRequest(
FollowupMessageCreateRequest(
content = _content,
tts = _tts,
embeds = Optional.missingOnEmpty(embeds),
embeds = Optional.missingOnEmpty(embeds.map(EmbedBuilder::toRequest)),
allowedMentions = _allowedMentions.map { it.build() },
components = Optional.missingOnEmpty(components.map(MessageComponentBuilder::build))
),
Expand All @@ -207,46 +173,32 @@ class PublicFollowupMessageCreateBuilder : RequestBuilder<MultipartFollowupMessa

@KordPreview
@KordDsl
class EphemeralFollowupMessageCreateBuilder(var content: String) :
RequestBuilder<MultipartFollowupMessageCreateRequest> {
class EphemeralFollowupMessageCreateBuilder : FollowupMessageBuilder<MultipartFollowupMessageCreateRequest> {

private var _content: Optional<String> = Optional.Missing()
override var content: String? by ::_content.delegate()

private var _tts: OptionalBoolean = OptionalBoolean.Missing
var tts: Boolean? by ::_tts.delegate()
override var tts: Boolean? by ::_tts.delegate()

private var _allowedMentions: Optional<AllowedMentionsBuilder> = Optional.Missing()
var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()

val components: MutableList<MessageComponentBuilder> = mutableListOf()

/**
* Configures the mentions that should trigger a mention (aka ping). Not calling this function will result in the default behavior
* (ping everything), calling this function but not configuring it before the request is build will result in all
* pings being ignored.
*/
@OptIn(ExperimentalContracts::class)
inline fun allowedMentions(block: AllowedMentionsBuilder.() -> Unit = {}) {
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
allowedMentions = (allowedMentions ?: AllowedMentionsBuilder()).apply(block)
}
override var allowedMentions: AllowedMentionsBuilder? by ::_allowedMentions.delegate()

@OptIn(ExperimentalContracts::class)
@KordPreview
inline fun actionRow(builder: ActionRowBuilder.() -> Unit) {
contract {
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
}
override val embeds: MutableList<EmbedBuilder> = mutableListOf()

override val components: MutableList<MessageComponentBuilder> = mutableListOf()

components.add(ActionRowBuilder().apply(builder))
}

override fun toRequest(): MultipartFollowupMessageCreateRequest =
MultipartFollowupMessageCreateRequest(
FollowupMessageCreateRequest(
content = Optional.Value(content),
content = _content,
embeds = Optional.missingOnEmpty(embeds.map(EmbedBuilder::toRequest)),
tts = _tts,
allowedMentions = _allowedMentions.map { it.build() },
components = Optional.missingOnEmpty(components.map(MessageComponentBuilder::build))
),
)

}

}