Skip to content

Instantly share code, notes, and snippets.

@Moire9
Created May 17, 2021 01:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Moire9/121ca7d89fc352ed6f22ab48a6608202 to your computer and use it in GitHub Desktop.
Save Moire9/121ca7d89fc352ed6f22ab48a6608202 to your computer and use it in GitHub Desktop.
Class to simplify eval commands for kotlin discord bots using kord. Currently uses slash commands, it would be easy to just use regular commands. To use, just initialize, and invoke with a string containing code to be executed.
import dev.kord.common.annotation.KordPreview
import dev.kord.core.Kord
import dev.kord.core.behavior.interaction.EphemeralInteractionResponseBehavior
import dev.kord.core.behavior.interaction.followUp
import dev.kord.core.entity.Guild
import dev.kord.core.entity.channel.Channel
import java.io.ByteArrayOutputStream
import java.io.PrintStream
import javax.script.ScriptEngineManager
import javax.script.ScriptException
@Suppress("unused") @KordPreview class EvalContext(
val client: Kord,
val channel: Channel,
val guild: Guild,
private val ack: EphemeralInteractionResponseBehavior
) {
private companion object {
/** This must contain the FULLY QUALIFIED NAME of this class!! */
const val CLASS_NAME = "EvalContext"
private val man = object : ScriptEngineManager(Thread.currentThread().contextClassLoader) {
operator fun invoke() = getEngineByExtension("kts")!!
}
}
private val buf = StringBuilder()
private var ret: Any? = Unit
private var error = true
internal suspend operator fun invoke(code: String) = try {
@Suppress("UNCHECKED_CAST")
ret = (man().eval("run<suspend $CLASS_NAME.()->Any?>{{$code}}")
as suspend EvalContext.() -> Any?)(this)
error = false
} catch (e: ScriptException) {
out("```" + buildString {
var a = true
var b = false
for (line in ByteArrayOutputStream().also { e.printStackTrace(PrintStream(it)) }.toString(Charsets.UTF_8)
.lines()) {
if (a) {
val s = line.split(':', limit = 2)[1].trimStart()
appendLine(s)
if (s.startsWith("Error: incomplete code")) break
a = false
continue
}
if (b && line.isBlank()) break
if (line.trimStart().startsWith('^')) b = true
appendLine(line)
}
}.also(System.err::print) + "```")
} catch (e: Throwable) {
out("```" + buildString {
append("Exception in thread \"${Thread.currentThread().name}\" ")
for (line in ByteArrayOutputStream().also { e.printStackTrace(PrintStream(it)) }.toString(Charsets.UTF_8)
.lines()) {
if (line.startsWith("\tat Line_1\$1\$1.invokeSuspend(Line_1.kts:")) {
appendLine("\tat <eval>(<eval>:${line.split(':', limit = 2)[1].dropLast(1)})")
break
}
appendLine(line)
}
}.also(System.err::print) + "```")
} finally {
try {
var out = buf.toString()
if (!error) {
val hr = ret != Unit
val b = out.isBlank()
if (b && !hr) out = "\u200B" else {
if (!b) out = "```\n$out\n```"
if (hr) out += "```Return value: ${ret.toString()}```"
}
}
ack.followUp(out)
} catch (e: Exception) { e.printStackTrace() }
}
fun out(message: Any?) { buf.append(message) }
fun out(message: Int) { buf.append(message) }
fun out(message: Long) { buf.append(message) }
fun out(message: Byte) { buf.append(message) }
fun out(message: Short) { buf.append(message) }
fun out(message: Char) { buf.append(message) }
fun out(message: Boolean) { buf.append(message) }
fun out(message: Float) { buf.append(message) }
fun out(message: Double) { buf.append(message) }
fun out(message: CharArray) { buf.append(message) }
fun outln(message: Any?) { buf.appendLine(message) }
fun outln(message: Int) { buf.appendLine(message) }
fun outln(message: Long) { buf.appendLine(message) }
fun outln(message: Byte) { buf.appendLine(message) }
fun outln(message: Short) { buf.appendLine(message) }
fun outln(message: Char) { buf.appendLine(message) }
fun outln(message: Boolean) { buf.appendLine(message) }
fun outln(message: Float) { buf.appendLine(message) }
fun outln(message: Double) { buf.appendLine(message) }
fun outln(message: CharArray) { buf.appendLine(message) }
fun outln() { buf.appendLine() }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment