diff --git a/build.gradle b/build.gradle index c8b58b6..42a3ee1 100644 --- a/build.gradle +++ b/build.gradle @@ -36,8 +36,8 @@ repositories { } dependencies { - compile("me.shedaniel:linkie-core:1.0.45") - compile("com.discord4j:discord4j-core:3.1.3-SNAPSHOT") { + compile("me.shedaniel:linkie-core:1.0.55") + compile("com.discord4j:discord4j-core:3.1.3") { force = true } compile "org.graalvm.js:js-scriptengine:20.2.0" @@ -68,6 +68,7 @@ compileKotlin { kotlinOptions.jvmTarget = "1.8" kotlinOptions { freeCompilerArgs = ["-Xopt-in=kotlin.RequiresOptIn", "-Xinline-classes"] + languageVersion = "1.4" } } diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/CommandBase.kt b/src/main/kotlin/me/shedaniel/linkie/discord/CommandBase.kt index ecb84ca..4cddaf3 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/CommandBase.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/CommandBase.kt @@ -16,6 +16,7 @@ package me.shedaniel.linkie.discord +import com.soywiz.korio.async.runBlockingNoJs import discord4j.common.util.Snowflake import discord4j.core.`object`.entity.Member import discord4j.core.`object`.entity.Message @@ -28,33 +29,40 @@ import me.shedaniel.linkie.InvalidUsageException import me.shedaniel.linkie.MappingsProvider import me.shedaniel.linkie.Namespace import me.shedaniel.linkie.discord.config.ConfigManager -import me.shedaniel.linkie.discord.utils.* +import me.shedaniel.linkie.discord.utils.addInlineField +import me.shedaniel.linkie.discord.utils.buildReactions +import me.shedaniel.linkie.discord.utils.content +import me.shedaniel.linkie.discord.utils.sendEdit +import me.shedaniel.linkie.discord.utils.sendEditEmbed +import me.shedaniel.linkie.discord.utils.sendEmbedMessage +import me.shedaniel.linkie.discord.utils.sendMessage +import me.shedaniel.linkie.discord.utils.tryRemoveAllReactions import reactor.core.publisher.Mono import java.time.Duration import java.util.* -typealias EmbedCreator = EmbedCreateSpec.() -> Unit +typealias EmbedCreator = suspend EmbedCreateSpec.() -> Unit fun embedCreator(creator: EmbedCreator) = creator fun MessageCreator.sendPages( initialPage: Int, maxPages: Int, - creator: EmbedCreateSpec.(Int) -> Unit, + creator: suspend EmbedCreateSpec.(Int) -> Unit, ) = sendPages(initialPage, maxPages, previous.author.get().id, creator) fun MessageCreator.sendPages( initialPage: Int, maxPages: Int, user: User, - creator: EmbedCreateSpec.(Int) -> Unit, + creator: suspend EmbedCreateSpec.(Int) -> Unit, ) = sendPages(initialPage, maxPages, user.id, creator) fun MessageCreator.sendPages( initialPage: Int, maxPages: Int, userId: Snowflake, - creator: EmbedCreateSpec.(Int) -> Unit, + creator: suspend EmbedCreateSpec.(Int) -> Unit, ) { var page = initialPage val builder = embedCreator { creator(this, page) } @@ -82,7 +90,7 @@ fun MessageCreator.sendPages( } interface CommandBase { - fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) + suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) fun postRegister() {} } @@ -113,16 +121,16 @@ data class MessageCreator( fun sendEmbed(content: EmbedCreator): Mono { return if (message == null) { - channel.sendEmbedMessage(previous, content) + channel.sendEmbedMessage(previous) { runBlockingNoJs { content() } } } else { - message!!.sendEditEmbed(content) + message!!.sendEditEmbed { runBlockingNoJs { content() } } }.doOnSuccess { message = it } } } open class SubCommandHolder : CommandBase { private val subcommands = mutableMapOf() - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { args.validateNotEmpty(prefix, "$cmd help") when (val subcommand = args[0].toLowerCase(Locale.ROOT)) { @@ -151,7 +159,7 @@ open class SubCommandHolder : CommandBase { val reactor = field.get(this) as SubCommandReactor subcommands[name] = object : SubCommandBase { override val name: String = name - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) = + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) = reactor.execute(event, message, prefix, user, cmd, args, channel) } @@ -160,13 +168,13 @@ open class SubCommandHolder : CommandBase { } fun subCmd(reactor: (event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) -> Unit): SubCommandReactor = object : SubCommandReactor { - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { reactor(event, message, prefix, user, cmd, args, channel) } } fun subCmd(reactor: CommandBase): SubCommandReactor = object : SubCommandReactor { - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { reactor.execute(event, message, prefix, user, cmd, args, channel) } } @@ -177,10 +185,10 @@ interface SubCommandBase : SubCommandReactor { } interface SubCommandReactor { - fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) + suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) } -inline fun MessageCreator.getCatching(user: User, run: () -> T): T { +inline suspend fun MessageCreator.getCatching(user: User, run: suspend () -> T): T { try { return run() } catch (t: Throwable) { diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/CommandHandler.kt b/src/main/kotlin/me/shedaniel/linkie/discord/CommandHandler.kt index c87289a..84686a7 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/CommandHandler.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/CommandHandler.kt @@ -36,7 +36,7 @@ object CommandHandler : CommandAcceptor { override fun getPrefix(event: MessageCreateEvent): String? = event.guildId.orElse(null)?.let { ConfigManager[it.asLong()].prefix } - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { if (cmd in commandMap) commandMap[cmd]!!.execute(event, message, prefix, user, cmd, args, channel) } diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/CommandMap.kt b/src/main/kotlin/me/shedaniel/linkie/discord/CommandMap.kt index f18a5eb..f2bf79a 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/CommandMap.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/CommandMap.kt @@ -76,7 +76,7 @@ class CommandMap(private val commandAcceptor: CommandAcceptor, private val defau } interface CommandAcceptor { - fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) + suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) fun getPrefix(event: MessageCreateEvent): String? } diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/TrickHandler.kt b/src/main/kotlin/me/shedaniel/linkie/discord/TrickHandler.kt index 0048f05..9c07105 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/TrickHandler.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/TrickHandler.kt @@ -30,7 +30,7 @@ object TrickHandler : CommandAcceptor { override fun getPrefix(event: MessageCreateEvent): String? = event.guildId.orElse(null)?.let { ConfigManager[it.asLong()].tricksPrefix } - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { if (event.guildId.isPresent) { val guildId = event.guildId.get().asLong() if (!ConfigManager[guildId].tricksEnabled) return diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/ValueKeeper.kt b/src/main/kotlin/me/shedaniel/linkie/discord/ValueKeeper.kt index b1e19fc..38fdca5 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/ValueKeeper.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/ValueKeeper.kt @@ -16,41 +16,45 @@ package me.shedaniel.linkie.discord +import com.soywiz.korio.async.runBlockingNoJs +import me.shedaniel.linkie.discord.utils.getOrNull import java.time.Duration import java.util.* import kotlin.concurrent.timerTask import kotlin.properties.ReadOnlyProperty @Suppress("MemberVisibilityCanBePrivate", "unused") -class ValueKeeper constructor(val timeToKeep: Duration, var value: Optional, val getter: () -> T) { +class ValueKeeper constructor(val timeToKeep: Duration, var value: Optional, val getter: suspend () -> T) { companion object { private val timer = Timer() } private var task: TimerTask? = null - constructor(timeToKeep: Duration, value: T, getter: () -> T) : this(timeToKeep, Optional.of(value), getter) - constructor(timeToKeep: Duration, getter: () -> T) : this(timeToKeep, getter(), getter) + constructor(timeToKeep: Duration, value: T, getter: suspend () -> T) : this(timeToKeep, Optional.of(value), getter) + constructor(timeToKeep: Duration, getter: suspend () -> T) : this(timeToKeep, runBlockingNoJs { getter() }, getter) init { - schedule() + runBlockingNoJs { + schedule() + } } - fun get(): T = value.orElseGet { getter().also { value = Optional.of(it); schedule() } } + suspend fun get(): T = value.getOrNull() ?: getter().also { value = Optional.of(it); schedule() } - fun clear() { + suspend fun clear() { value = Optional.empty() System.gc() } - fun schedule() { + suspend fun schedule() { task?.cancel() - task = timerTask { clear() } + task = timerTask { runBlockingNoJs { clear() } } timer.schedule(task, timeToKeep.toMillis()) } } -fun valueKeeper(timeToKeep: Duration = Duration.ofMinutes(2), getter: () -> T): ReadOnlyProperty { +fun valueKeeper(timeToKeep: Duration = Duration.ofMinutes(2), getter: suspend () -> T): ReadOnlyProperty { val keeper = ValueKeeper(timeToKeep, getter) - return ReadOnlyProperty { _, _ -> keeper.get() } + return ReadOnlyProperty { _, _ -> runBlockingNoJs { keeper.get() } } } \ No newline at end of file diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/commands/AWCommand.kt b/src/main/kotlin/me/shedaniel/linkie/discord/commands/AWCommand.kt index fe47fcc..601dee4 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/commands/AWCommand.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/commands/AWCommand.kt @@ -27,7 +27,7 @@ import me.shedaniel.linkie.discord.utils.setTimestampToNow import me.shedaniel.linkie.discord.validateEmpty object AWCommand : CommandBase { - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { args.validateEmpty(prefix, cmd) message.sendEmbed { setFooter("Requested by " + user.discriminatedName, user.avatarUrl) diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/commands/AboutCommand.kt b/src/main/kotlin/me/shedaniel/linkie/discord/commands/AboutCommand.kt index b2040d1..43a7ede 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/commands/AboutCommand.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/commands/AboutCommand.kt @@ -26,7 +26,7 @@ import me.shedaniel.linkie.discord.utils.* import me.shedaniel.linkie.discord.validateEmpty object AboutCommand : CommandBase { - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { args.validateEmpty(prefix, cmd) message.sendEmbed { setTitle("About Linkie") diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/commands/AddTrickCommand.kt b/src/main/kotlin/me/shedaniel/linkie/discord/commands/AddTrickCommand.kt index 27cff50..bd21f66 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/commands/AddTrickCommand.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/commands/AddTrickCommand.kt @@ -34,7 +34,7 @@ import me.shedaniel.linkie.discord.validateUsage import java.util.* object AddTrickCommand : CommandBase { - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { LinkieScripting.validateGuild(event) args.validateUsage(prefix, 2..Int.MAX_VALUE, "$cmd [--script] ") val name = args.first() diff --git a/src/main/kotlin/me/shedaniel/linkie/discord/commands/EvaluateCommand.kt b/src/main/kotlin/me/shedaniel/linkie/discord/commands/EvaluateCommand.kt index 92acc5a..601a043 100644 --- a/src/main/kotlin/me/shedaniel/linkie/discord/commands/EvaluateCommand.kt +++ b/src/main/kotlin/me/shedaniel/linkie/discord/commands/EvaluateCommand.kt @@ -28,7 +28,7 @@ import me.shedaniel.linkie.discord.scripting.push import me.shedaniel.linkie.discord.validateNotEmpty object EvaluateCommand : CommandBase { - override fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { + override suspend fun execute(event: MessageCreateEvent, message: MessageCreator, prefix: String, user: User, cmd: String, args: MutableList, channel: MessageChannel) { args.validateNotEmpty(prefix, "$cmd