Skip to content

Commit 62331ed

Browse files
committed
refactor(yogurt): move scripting logic into single file
[skip ci]
1 parent e52de51 commit 62331ed

7 files changed

Lines changed: 77 additions & 100 deletions

File tree

yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/YogurtApp.kt

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package org.ntqqrev.yogurt
22

3-
import com.dokar.quickjs.QuickJs
43
import com.github.ajalt.mordant.rendering.TextColors
54
import com.github.ajalt.mordant.terminal.Terminal
65
import io.ktor.http.*
@@ -11,7 +10,6 @@ import io.ktor.server.cio.*
1110
import io.ktor.server.engine.*
1211
import io.ktor.server.plugins.contentnegotiation.*
1312
import io.ktor.server.plugins.cors.routing.*
14-
import io.ktor.server.plugins.di.*
1513
import io.ktor.server.routing.*
1614
import io.ktor.server.sse.*
1715
import io.ktor.server.websocket.*
@@ -25,8 +23,7 @@ import org.ntqqrev.milky.milkyVersion
2523
import org.ntqqrev.yogurt.config.loadConfigAndUpdate
2624
import org.ntqqrev.yogurt.debug.configureDebugFaceDetailsApi
2725
import org.ntqqrev.yogurt.fs.withFs
28-
import org.ntqqrev.yogurt.script.createScriptEnvironment
29-
import org.ntqqrev.yogurt.script.loadScripts
26+
import org.ntqqrev.yogurt.scripting.configureScripting
3027
import org.ntqqrev.yogurt.util.*
3128
import kotlin.time.Duration.Companion.milliseconds
3229

@@ -147,12 +144,7 @@ object YogurtApp {
147144
}
148145
}
149146

150-
val qjs = createScriptEnvironment()
151-
152-
dependencies {
153-
provide<MilkyContext> { ctx }
154-
provide<QuickJs> { qjs } cleanup { it.close() }
155-
}
147+
configureScripting()
156148
}
157149

158150
monitor.subscribe(ApplicationStarted) {
@@ -162,7 +154,6 @@ object YogurtApp {
162154

163155
launch {
164156
botLogin()
165-
loadScripts()
166157
}
167158
}
168159
}

yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/script/Handles.kt

Lines changed: 0 additions & 9 deletions
This file was deleted.

yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/script/Loader.kt

Lines changed: 0 additions & 50 deletions
This file was deleted.

yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/script/Script.kt

Lines changed: 0 additions & 6 deletions
This file was deleted.

yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/script/Environment.kt renamed to yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/scripting/Configure.kt

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
1-
package org.ntqqrev.yogurt.script
1+
package org.ntqqrev.yogurt.scripting
22

33
import com.dokar.quickjs.QuickJs
44
import com.dokar.quickjs.binding.ObjectBindingScope
55
import com.dokar.quickjs.binding.define
66
import io.ktor.server.application.*
77
import io.ktor.server.plugins.di.*
8-
import kotlinx.coroutines.Dispatchers
9-
import kotlinx.coroutines.runBlocking
10-
import kotlinx.serialization.ExperimentalSerializationApi
8+
import kotlinx.coroutines.*
119
import org.ntqqrev.acidify.AbstractBot
1210
import org.ntqqrev.acidify.milky.MilkyContext
1311
import org.ntqqrev.acidify.milky.api.MilkyApiHandler
1412
import org.ntqqrev.acidify.milky.api.handler.*
1513
import org.ntqqrev.acidify.milky.mediaSourceScoped
1614
import org.ntqqrev.milky.milkyJsonModule
17-
import org.ntqqrev.yogurt.script.stdlib.defineConsole
18-
import org.ntqqrev.yogurt.script.stdlib.defineHttp
15+
import org.ntqqrev.yogurt.fs.withFs
16+
import org.ntqqrev.yogurt.scripting.stdlib.defineStdlibConsole
17+
import org.ntqqrev.yogurt.scripting.stdlib.defineStdlibHttp
18+
import org.ntqqrev.yogurt.scriptsPath
1919
import kotlin.time.DurationUnit
2020
import kotlin.time.measureTime
2121

22+
const val rootHandle = "yogurt"
23+
const val apiHandle = "api"
24+
const val eventHandle = "event"
25+
26+
const val internalApiHandle = "__yogurtInternal_api"
27+
const val internalEventMapHandle = "__yogurtInternal_eventMap"
28+
const val internalEmitHandle = "__yogurtInternal_emit"
29+
30+
class Script(
31+
val name: String,
32+
val content: String,
33+
)
34+
2235
context(ctx: MilkyContext)
23-
suspend fun Application.createScriptEnvironment() =
24-
QuickJs.create(jobDispatcher = Dispatchers.Default).apply {
25-
defineConsole()
26-
defineHttp()
36+
suspend fun Application.configureScripting() = QuickJs.create(jobDispatcher = Dispatchers.Default).apply {
37+
defineStdlibConsole()
38+
defineStdlibHttp()
2739

2840
evaluate<Any?>(
2941
"""
@@ -132,15 +144,20 @@ suspend fun Application.createScriptEnvironment() =
132144
}
133145
""".trimIndent()
134146
)
147+
148+
monitor.subscribe(ApplicationStarted) {
149+
this@configureScripting.launch {
150+
loadScripts()
151+
}
152+
}
135153
}
136154

137-
@OptIn(ExperimentalSerializationApi::class)
138155
context(
139156
qjs: QuickJs,
140157
scope: ObjectBindingScope,
141158
ctx: MilkyContext,
142159
)
143-
inline fun <reified T : Any, reified R : Any> Application.defineJsApi(
160+
private inline fun <reified T : Any, reified R : Any> Application.defineJsApi(
144161
handler: MilkyApiHandler<T, R>
145162
) {
146163
val methodName = handler.path.removePrefix("/")
@@ -185,4 +202,43 @@ inline fun <reified T : Any, reified R : Any> Application.defineJsApi(
185202
throw e
186203
}
187204
}
205+
}
206+
207+
context(ctx: MilkyContext)
208+
private suspend fun QuickJs.loadScripts() = withFs {
209+
val logger = ctx.application.dependencies
210+
.resolve<AbstractBot>()
211+
.createLogger("ScriptLoader")
212+
213+
if (!exists(scriptsPath)) {
214+
createDirectories(scriptsPath)
215+
}
216+
217+
val scripts = list(scriptsPath)
218+
.filter { it.name.endsWith(".yogurtx.js") }
219+
.map {
220+
ctx.async {
221+
Script(
222+
name = it.name,
223+
content = withContext(Dispatchers.IO) {
224+
it.readText()
225+
}
226+
)
227+
}
228+
}
229+
.awaitAll()
230+
if (scripts.isNotEmpty()) {
231+
scripts.forEach {
232+
evaluate<Any?>(
233+
code = it.content,
234+
filename = it.name,
235+
asModule = true,
236+
)
237+
logger.i { "脚本 ${it.name.removeSuffix(".yogurtx.js")} 加载完成" }
238+
}
239+
logger.i { "加载了 ${scripts.size} 个脚本" }
240+
ctx.eventFlow.collect {
241+
evaluate<Any?>("$internalEmitHandle(${milkyJsonModule.encodeToString(it)})")
242+
}
243+
}
188244
}

yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/script/stdlib/Console.kt renamed to yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/scripting/stdlib/Console.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
package org.ntqqrev.yogurt.script.stdlib
1+
package org.ntqqrev.yogurt.scripting.stdlib
22

33
import com.dokar.quickjs.QuickJs
44
import com.dokar.quickjs.binding.define
55
import kotlin.time.TimeMark
66
import kotlin.time.TimeSource
77

8-
fun QuickJs.defineConsole() = define("console") {
8+
fun QuickJs.defineStdlibConsole() = define("console") {
99
val consoleTimers = mutableMapOf<String, TimeMark>()
1010
val consoleCounts = mutableMapOf<String, Int>()
1111
var consoleGroupDepth = 0

yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/script/stdlib/Http.kt renamed to yogurt/src/commonMain/kotlin/org/ntqqrev/yogurt/scripting/stdlib/Http.kt

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
1-
package org.ntqqrev.yogurt.script.stdlib
1+
package org.ntqqrev.yogurt.scripting.stdlib
22

33
import com.dokar.quickjs.QuickJs
44
import com.dokar.quickjs.binding.JsObject
55
import com.dokar.quickjs.binding.define
6-
import io.ktor.client.HttpClient
7-
import io.ktor.client.request.get
8-
import io.ktor.client.request.header
9-
import io.ktor.client.request.post
10-
import io.ktor.client.request.setBody
11-
import io.ktor.client.statement.HttpResponse
12-
import io.ktor.client.statement.bodyAsBytes
13-
import io.ktor.client.statement.bodyAsText
6+
import io.ktor.client.*
7+
import io.ktor.client.request.*
8+
import io.ktor.client.statement.*
149

1510
class HttpRequestOptions(
1611
val method: String,
@@ -46,7 +41,7 @@ class HttpRequestOptions(
4641
}
4742

4843
@OptIn(ExperimentalUnsignedTypes::class)
49-
fun QuickJs.defineHttp() = define("http") {
44+
fun QuickJs.defineStdlibHttp() = define("http") {
5045
val httpClient = HttpClient()
5146

5247
fun Array<Any?>.extractParams(): Pair<String, HttpRequestOptions> {

0 commit comments

Comments
 (0)