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 improvements #387

Merged
merged 9 commits into from
Sep 14, 2021
Merged
Show file tree
Hide file tree
Changes from 6 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
81 changes: 54 additions & 27 deletions core/src/main/kotlin/Kord.kt
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ class Kord(
get() = defaultSupplier.getGlobalApplicationCommands(resources.applicationId)



/**
* The default supplier, obtained through Kord's [resources] and configured through [KordBuilder.defaultStrategy].
* By default a strategy from [EntitySupplyStrategy.rest].
Expand Down Expand Up @@ -371,6 +370,10 @@ class Kord(
return defaultSupplier.getGuildApplicationCommands(resources.applicationId, guildId)
}

suspend fun getOriginalInteractionResponse(token: String): Message? {
return EntitySupplyStrategy.rest.supply(this).getOriginalInteractionOrNull(resources.applicationId, token)
}
HopeBaron marked this conversation as resolved.
Show resolved Hide resolved

suspend fun getGuildApplicationCommand(guildId: Snowflake, commandId: Snowflake): GuildApplicationCommand {
return defaultSupplier.getGuildApplicationCommand(resources.applicationId, guildId, commandId)
}
Expand All @@ -381,12 +384,18 @@ class Kord(
}


suspend inline fun <reified T: GuildApplicationCommand> getGuildApplicationCommandOf(guildId: Snowflake, commandId: Snowflake): T {
suspend inline fun <reified T : GuildApplicationCommand> getGuildApplicationCommandOf(
guildId: Snowflake,
commandId: Snowflake
): T {
return defaultSupplier.getGuildApplicationCommandOf(resources.applicationId, guildId, commandId)
}


suspend inline fun <reified T: GuildApplicationCommand> getGuildApplicationCommandOfOrNull(guildId: Snowflake, commandId: Snowflake): T? {
suspend inline fun <reified T : GuildApplicationCommand> getGuildApplicationCommandOfOrNull(
guildId: Snowflake,
commandId: Snowflake
): T? {
return defaultSupplier.getGuildApplicationCommandOfOrNull(resources.applicationId, guildId, commandId)
}

Expand Down Expand Up @@ -418,8 +427,12 @@ class Kord(
builder: ChatInputCreateBuilder.() -> Unit = {},
): GlobalChatInputCommand {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val request = ChatInputCreateBuilder(name, description).apply(builder).toRequest()
val response = rest.interaction.createGlobalApplicationCommand(resources.applicationId, request)
val response = rest.interaction.createGlobalChatInputApplicationCommand(
resources.applicationId,
name,
description,
builder
)
val data = ApplicationCommandData.from(response)
return GlobalChatInputCommand(data, rest.interaction)
}
Expand All @@ -442,8 +455,8 @@ class Kord(
builder: UserCommandCreateBuilder.() -> Unit = {},
): GlobalUserCommand {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val request = UserCommandCreateBuilder(name).apply(builder).toRequest()
val response = rest.interaction.createGlobalApplicationCommand(resources.applicationId, request)
val response =
rest.interaction.createGlobalUserCommandApplicationCommand(resources.applicationId, name, builder)
val data = ApplicationCommandData.from(response)
return GlobalUserCommand(data, rest.interaction)
}
Expand All @@ -455,8 +468,7 @@ class Kord(
): Flow<GlobalApplicationCommand> {

contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val request = MultiApplicationCommandBuilder().apply(builder).build()
val commands = rest.interaction.createGlobalApplicationCommands(resources.applicationId, request)
val commands = rest.interaction.createGlobalApplicationCommands(resources.applicationId, builder)
return flow {
commands.forEach {
val data = ApplicationCommandData.from(it)
Expand All @@ -473,8 +485,14 @@ class Kord(
builder: ChatInputCreateBuilder.() -> Unit = {},
): GuildChatInputCommand {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val request = ChatInputCreateBuilder(name, description).apply(builder).toRequest()
val response = rest.interaction.createGuildApplicationCommand(resources.applicationId, guildId, request)
val response =
rest.interaction.createGuildChatInputApplicationCommand(
resources.applicationId,
guildId,
name,
description,
builder
)
val data = ApplicationCommandData.from(response)
return GuildChatInputCommand(data, rest.interaction)
}
Expand All @@ -487,8 +505,12 @@ class Kord(
builder: MessageCommandCreateBuilder.() -> Unit = {},
): GuildMessageCommand {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val request = MessageCommandCreateBuilder(name).apply(builder).toRequest()
val response = rest.interaction.createGuildApplicationCommand(resources.applicationId, guildId, request)
val response = rest.interaction.createGuildMessageCommandApplicationCommand(
resources.applicationId,
guildId,
name,
builder
)
val data = ApplicationCommandData.from(response)
return GuildMessageCommand(data, rest.interaction)
}
Expand All @@ -500,8 +522,13 @@ class Kord(
builder: UserCommandCreateBuilder.() -> Unit = {},
): GuildUserCommand {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val request = UserCommandCreateBuilder(name).apply(builder).toRequest()
val response = rest.interaction.createGuildApplicationCommand(resources.applicationId, guildId, request)
val response = rest.interaction.createGuildUserCommandApplicationCommand(
resources.applicationId,
guildId,
name,
builder
)

val data = ApplicationCommandData.from(response)
return GuildUserCommand(data, rest.interaction)
}
Expand All @@ -513,9 +540,9 @@ class Kord(
builder: MultiApplicationCommandBuilder.() -> Unit,
): Flow<GuildApplicationCommand> {
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
val request = MultiApplicationCommandBuilder().apply(builder).build()

val commands = rest.interaction.createGuildApplicationCommands(resources.applicationId, guildId, request)
val commands = rest.interaction.createGuildApplicationCommands(resources.applicationId, guildId, builder)

return flow {
commands.forEach {
val data = ApplicationCommandData.from(it)
Expand All @@ -524,27 +551,27 @@ class Kord(
}
}

suspend fun editApplicationCommandPermissions(
applicationId: Snowflake,
@OptIn(ExperimentalContracts::class)
suspend inline fun editApplicationCommandPermissions(
guildId: Snowflake,
commandId: Snowflake,
builder: ApplicationCommandPermissionsModifyBuilder.() -> Unit,
) {
val request = ApplicationCommandPermissionsModifyBuilder().apply(builder).toRequest()

rest.interaction.editApplicationCommandPermissions(applicationId, guildId, commandId, request)
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
rest.interaction.editApplicationCommandPermissions(resources.applicationId, guildId, commandId, builder)
}

suspend fun bulkEditApplicationCommandPermissions(
applicationId: Snowflake,

@OptIn(ExperimentalContracts::class)
suspend inline fun bulkEditApplicationCommandPermissions(
guildId: Snowflake,
builder: ApplicationCommandPermissionsBulkModifyBuilder.() -> Unit,
) {
val request = ApplicationCommandPermissionsBulkModifyBuilder().apply(builder).toRequest()

rest.interaction.bulkEditApplicationCommandPermissions(applicationId, guildId, request)
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }
rest.interaction.bulkEditApplicationCommandPermissions(resources.applicationId, guildId, builder)
}


}

/**
Expand Down
11 changes: 3 additions & 8 deletions core/src/main/kotlin/behavior/GuildBehavior.kt
Original file line number Diff line number Diff line change
Expand Up @@ -978,13 +978,8 @@ inline fun GuildBehavior.requestMembers(builder: RequestGuildMembersBuilder.() -
@OptIn(ExperimentalContracts::class)

suspend inline fun GuildBehavior.bulkEditSlashCommandPermissions(noinline builder: ApplicationCommandPermissionsBulkModifyBuilder.() -> Unit) {
contract {
callsInPlace(builder, InvocationKind.EXACTLY_ONCE)
}

kord.bulkEditApplicationCommandPermissions(
kord.selfId,
id,
builder
)
contract { callsInPlace(builder, InvocationKind.EXACTLY_ONCE) }

kord.bulkEditApplicationCommandPermissions(id, builder)
}
28 changes: 14 additions & 14 deletions core/src/main/kotlin/exception/EntityNotFoundException.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,40 +40,40 @@ class EntityNotFoundException : Exception {
inline fun selfNotFound(): Nothing =
throw EntityNotFoundException("Self user not found")

fun roleNotFound(guildId: Snowflake, roleId: Snowflake): Nothing =
inline fun roleNotFound(guildId: Snowflake, roleId: Snowflake): Nothing =
guildEntityNotFound("Role", guildId = guildId, id = roleId)

fun banNotFound(guildId: Snowflake, userId: Snowflake): Nothing =
inline fun banNotFound(guildId: Snowflake, userId: Snowflake): Nothing =
guildEntityNotFound("Ban", guildId = guildId, id = userId)

fun emojiNotFound(guildId: Snowflake, emojiId: Snowflake): Nothing =
inline fun emojiNotFound(guildId: Snowflake, emojiId: Snowflake): Nothing =
guildEntityNotFound("GuildEmoji", guildId = guildId, id = emojiId)

fun webhookNotFound(webhookId: Snowflake): Nothing =
inline fun webhookNotFound(webhookId: Snowflake): Nothing =
entityNotFound("Webhook", webhookId)

fun inviteNotFound(code: String): Nothing =
inline fun inviteNotFound(code: String): Nothing =
throw EntityNotFoundException("Invite with code $code was not found.")

fun widgetNotFound(id: Snowflake): Nothing =
inline fun widgetNotFound(id: Snowflake): Nothing =
throw EntityNotFoundException("Widget for guild ${id.value} was not found.")

fun templateNotFound(code: String): Nothing =
inline fun templateNotFound(code: String): Nothing =
throw EntityNotFoundException("Template $code was not found.")

fun welcomeScreenNotFound(guildId: Snowflake): Nothing =
inline fun welcomeScreenNotFound(guildId: Snowflake): Nothing =
throw EntityNotFoundException("Welcome screen for guild $guildId was not found.")

fun stageInstanceNotFound(channelId: Snowflake): Nothing =
throw EntityNotFoundException("Stage instance for channel $channelId was not found")
inline fun stageInstanceNotFound(channelId: Snowflake): Nothing =
throw EntityNotFoundException("Stage instance for channel $channelId was not found.")

fun applicationCommandPermissionsNotFound(commandId: Snowflake): Nothing =
inline fun applicationCommandPermissionsNotFound(commandId: Snowflake): Nothing =
entityNotFound("ApplicationCommand", commandId)

inline fun <reified T : ApplicationCommand> applicationCommandNotFound(commandId: Snowflake): Nothing =
entityNotFound(T::class.simpleName!!, commandId)


inline fun interactionNotFound(token: String): Nothing =
throw EntityNotFoundException("Interaction with token $token was not found.")
}
}

}
10 changes: 10 additions & 0 deletions core/src/main/kotlin/supplier/RestEntitySupplier.kt
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,16 @@ class RestEntitySupplier(val kord: Kord) : EntitySupplier {
}
}

suspend fun getOriginalInteractionOrNull(applicationId: Snowflake, token: String): Message? = catchNotFound {
val response = interaction.getInteractionResponse(applicationId, token)
val data = MessageData.from(response)
Message(data, kord)
}


suspend fun getOriginalInteraction(applicationId: Snowflake, token: String): Message {
return getOriginalInteractionOrNull(applicationId, token) ?: EntityNotFoundException.interactionNotFound(token)
}
override fun getGuildApplicationCommandPermissions(
applicationId: Snowflake,
guildId: Snowflake,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ interface PersistentMessageCreateBuilder : MessageCreateBuilder {
/**
* Adds a file with the [name] and [content] to the attachments.
*/
fun addFile(name: String, content: InputStream) {
files += NamedFile(name, content)
fun addFile(name: String, content: InputStream): NamedFile {
val namedFile = NamedFile(name, content)
files += namedFile
return namedFile
}

/**
* Adds a file with the given [path] to the attachments.
*/
suspend fun addFile(path: Path) = withContext(Dispatchers.IO) {
suspend fun addFile(path: Path): NamedFile = withContext(Dispatchers.IO) {
addFile(path.fileName.toString(), Files.newInputStream(path))
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,17 @@ interface PersistentMessageModifyBuilder : MessageModifyBuilder {

var attachments: MutableList<DiscordAttachment>?

fun addFile(name: String, content: InputStream) {
fun addFile(name: String, content: InputStream): NamedFile {
val namedFile = NamedFile(name, content)

files = (files ?: mutableListOf()).also {
it.add(NamedFile(name, content))
it.add(namedFile)
}

return namedFile
}

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

Expand Down
7 changes: 7 additions & 0 deletions rest/src/main/kotlin/route/Route.kt
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,13 @@ sealed class Route<T>(
NoStrategy
)

object OriginalInteractionResponseGet :
Route<DiscordMessage>(
HttpMethod.Get,
"/webhooks/${ApplicationId}/${InteractionToken}/messages/@original",
DiscordMessage.serializer()
)

object OriginalInteractionResponseModify :
Route<DiscordMessage>(
HttpMethod.Patch,
Expand Down
Loading