Skip to content

Commit

Permalink
Make suggestions also threaded
Browse files Browse the repository at this point in the history
Signed-off-by: shedaniel <daniel@shedaniel.me>
  • Loading branch information
shedaniel committed Jun 10, 2022
1 parent eae4c88 commit d863ffe
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import me.shedaniel.linkie.discord.utils.sendEmbedMessage
import java.time.Duration
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionException
import java.util.concurrent.ExecutionException
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -86,6 +85,8 @@ class CommandHandler(
throwable2.printStackTrace()
}
}
} finally {
rateLimiter.handledCommand(user, cmd, mutableMapOf("args" to args))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ open class RateLimiter(val maxRequestPer10Sec: Int) {
return log.count { it.userId == userId } <= maxRequestPer10Sec
}
}

open fun handledCommand(user: User, cmd: String, args: Map<String, Any>) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,13 @@ package me.shedaniel.linkie.discord.scommands

import discord4j.common.util.Snowflake
import discord4j.core.GatewayDiscordClient
import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent
import discord4j.core.`object`.command.ApplicationCommandInteractionOption
import discord4j.core.`object`.command.ApplicationCommandOption.Type.*
import discord4j.core.`object`.entity.Role
import discord4j.core.`object`.entity.User
import discord4j.core.`object`.entity.channel.Channel
import discord4j.core.event.domain.interaction.ChatInputAutoCompleteEvent
import discord4j.core.event.domain.interaction.ChatInputInteractionEvent
import discord4j.core.`object`.command.ApplicationCommandOption
import discord4j.discordjson.json.ApplicationCommandData
import discord4j.discordjson.json.ApplicationCommandOptionChoiceData
import discord4j.discordjson.json.ApplicationCommandRequest
Expand All @@ -43,7 +42,6 @@ import me.shedaniel.linkie.discord.utils.user
import reactor.core.publisher.Mono
import java.util.concurrent.CompletableFuture
import java.util.concurrent.CompletionException
import java.util.concurrent.ExecutionException
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
Expand Down Expand Up @@ -126,10 +124,10 @@ class SlashCommands(
globalCommand(commandBuilder)
}

fun guildCommand(guild: Long, command: SlashCommand) =
guildCommand(Snowflake.of(guild), command)
fun guildCommand(guild: Long, command: SlashCommand, errorCallback: (Throwable) -> Unit = {}) =
guildCommand(Snowflake.of(guild), command, errorCallback)

fun guildCommand(guild: Snowflake, command: SlashCommand) {
fun guildCommand(guild: Snowflake, command: SlashCommand, errorCallback: (Throwable) -> Unit = {}) {
for (cmd in command.cmds) {
guildHandlers[GuildCommandKey(guild, cmd)] = buildHandler(command, cmd)

Expand Down Expand Up @@ -167,7 +165,7 @@ class SlashCommands(
}

println("Registering guild (${guild.asString()}) command /$cmd")
createGuildCommand(guild, command, cmd).subscribe { newData ->
createGuildCommand(guild, command, cmd, errorCallback).subscribe { newData ->
registeredGuildCommands[GuildCommandKey(guild, cmd)] = newData
}
}
Expand All @@ -185,7 +183,7 @@ class SlashCommands(
.doOnError { errorHandler("Unable to create global command: " + it.message) }
.onErrorResume { Mono.empty() }

private fun createGuildCommand(guildId: Snowflake, command: SlashCommand, cmd: String) =
private fun createGuildCommand(guildId: Snowflake, command: SlashCommand, cmd: String, errorCallback: (Throwable) -> Unit) =
client.restClient.applicationService
.createGuildApplicationCommand(applicationId, guildId.asLong(), buildRequest(command, cmd))
.doOnError { errorHandler("Unable to create guild command: " + it.message) }
Expand Down Expand Up @@ -284,7 +282,8 @@ class SlashCommands(
return map
}

if (!rateLimiter.allow(event.user, cmd, event.collectOptions())) {
val options = event.collectOptions()
if (!rateLimiter.allow(event.user, cmd, options)) {
val exception = RateLimitException(rateLimiter.maxRequestPer10Sec)
if (throwableHandler.shouldError(exception)) {
try {
Expand Down Expand Up @@ -333,6 +332,9 @@ class SlashCommands(
}
null
}
.handle { _, _ ->
rateLimiter.handledCommand(event.user, cmd, options)
}
.join()
}, autoCompleter = { event ->
val optionsGetter = WeakOptionsGetter.of(command, event).asSuggestion(event.commandName)
Expand All @@ -345,13 +347,16 @@ class SlashCommands(
options = it.toList().take(25)
}
}
runCatching {
CompletableFuture.runAsync({
if (!suggestCompletions(command, optionsGetter, command.options, sink, event.focusedOption) && !(command.suggest(command, optionsGetter, sink).let { sink.suggested })) {
}
}.exceptionOrNull()?.printStackTrace()
if (sink.suggested) {
event.respondWithSuggestions(options!!).subscribe()
}
}, executor).orTimeout(10, TimeUnit.SECONDS)
.thenAccept {
if (sink.suggested) {
event.respondWithSuggestions(options!!).subscribe()
}
}
.join()
})

private fun buildRequest(command: SlashCommand, cmd: String): ApplicationCommandRequest =
Expand Down
7 changes: 7 additions & 0 deletions src/main/kotlin/me/shedaniel/linkie/discord/LinkieBot.kt
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,13 @@ fun main() {
} from ${user.discriminatedName}")
return super.allow(user, cmd, args)
}

override fun handledCommand(user: User, cmd: String, args: Map<String, Any>) {
info("Handled command /$cmd ${
args.entries.joinToString(" ")
{ "${it.key}: ${it.value}" }
} from ${user.discriminatedName}")
}
}
val slashCommands = SlashCommands(this, LinkieThrowableHandler, ::warn, debug = isDebug, rateLimiter = rateLimiter)
TricksManager.listen(slashCommands)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ data class Trick(
override val contentType: ContentType,
override val flags: List<Char> = emptyList(),
override val content: String,
var noSlashCommand: Boolean = false,
) : TrickBase {
override val requirePermissionForFlags: Boolean
get() = true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,14 @@ object TricksManager {
.asSlashCommand("Run trick ${trick.name}", listOf(trick.name)))
}.exceptionOrNull()?.printStackTrace()
}
TricksManager.tricks.values.forEach { trick ->
TricksManager.tricks.forEach { (uuid, trick) ->
if (trick.noSlashCommand) return@forEach
runCatching {
slashCommands.guildCommand(trick.guildId, TrickBasedCommand(trick)
.asSlashCommand("Run trick ${trick.name}", listOf(trick.name)))
.asSlashCommand("Run trick ${trick.name}", listOf(trick.name))) { _ ->
trick.noSlashCommand = true
saveTrick(uuid)
}
}.exceptionOrNull()?.printStackTrace()
}
ArrayList(slashCommands.globalCommands + slashCommands.registeredCommands.values).distinctBy { it.name() }.forEach { commands ->
Expand Down Expand Up @@ -124,11 +128,16 @@ object TricksManager {
}

fun save() {
tricks.forEach { (uuid, trick) ->
val trickFile = File(tricksFolder, "$uuid.json")
if (trickFile.exists().not()) {
trickFile.writeText(json.encodeToString(Trick.serializer(), trick))
}
tricks.forEach { (uuid, _) ->
saveTrick(uuid)
}
}

fun saveTrick(uuid: UUID) {
val trick = tricks[uuid] ?: return
val trickFile = File(tricksFolder, "$uuid.json")
if (trickFile.exists().not()) {
trickFile.writeText(json.encodeToString(Trick.serializer(), trick))
}
}

Expand Down

0 comments on commit d863ffe

Please sign in to comment.