feat(scripting): module exports

- add currentSide global
- add script name rule
- add displayName
This commit is contained in:
rhunk
2023-12-25 02:02:27 +01:00
parent 4a4aa28ccf
commit 3edd6ed723
7 changed files with 40 additions and 13 deletions

View File

@ -64,6 +64,7 @@ class ModDatabase(
"scripts" to listOf(
"name VARCHAR PRIMARY KEY",
"version VARCHAR NOT NULL",
"displayName VARCHAR",
"description VARCHAR",
"author VARCHAR NOT NULL",
"enabled BOOLEAN"
@ -266,6 +267,7 @@ class ModDatabase(
ModuleInfo(
name = cursor.getStringOrNull("name")!!,
version = cursor.getStringOrNull("version")!!,
displayName = cursor.getStringOrNull("displayName"),
description = cursor.getStringOrNull("description"),
author = cursor.getStringOrNull("author"),
grantedPermissions = emptyList()
@ -305,14 +307,18 @@ class ModDatabase(
}
availableScripts.forEach { script ->
if (!enabledScriptPaths.contains(script.name)) {
database.execSQL("INSERT OR REPLACE INTO scripts (name, version, description, author, enabled) VALUES (?, ?, ?, ?, ?)", arrayOf(
script.name,
script.version,
script.description,
script.author,
0
))
if (!enabledScriptPaths.contains(script.name) || script != enabledScripts.find { it.name == script.name }) {
database.execSQL(
"INSERT OR REPLACE INTO scripts (name, version, displayName, description, author, enabled) VALUES (?, ?, ?, ?, ?, ?)",
arrayOf(
script.name,
script.version,
script.displayName,
script.description,
script.author,
0
)
)
}
}
}

View File

@ -7,6 +7,7 @@ import me.rhunk.snapenhance.bridge.scripting.AutoReloadListener
import me.rhunk.snapenhance.bridge.scripting.IPCListener
import me.rhunk.snapenhance.bridge.scripting.IScripting
import me.rhunk.snapenhance.common.scripting.ScriptRuntime
import me.rhunk.snapenhance.common.scripting.bindings.BindingSide
import me.rhunk.snapenhance.common.scripting.impl.ConfigInterface
import me.rhunk.snapenhance.common.scripting.impl.ConfigTransactionType
import me.rhunk.snapenhance.common.scripting.type.ModuleInfo
@ -63,6 +64,7 @@ class RemoteScriptManager(
fun init() {
runtime.buildModuleObject = { module ->
putConst("currentSide", this, BindingSide.MANAGER.key)
module.registerBindings(
ManagerIPC(ipcListeners),
InterfaceManager(),

View File

@ -64,7 +64,7 @@ class ScriptsSection : Section() {
.weight(1f)
.padding(end = 8.dp)
) {
Text(text = script.name, fontSize = 20.sp,)
Text(text = script.displayName ?: script.name, fontSize = 20.sp,)
Text(text = script.description ?: "No description", fontSize = 14.sp,)
}
IconButton(onClick = { openSettings = !openSettings }) {

View File

@ -6,6 +6,7 @@ import me.rhunk.snapenhance.common.scripting.bindings.AbstractBinding
import me.rhunk.snapenhance.common.scripting.bindings.BindingsContext
import me.rhunk.snapenhance.common.scripting.ktx.contextScope
import me.rhunk.snapenhance.common.scripting.ktx.putFunction
import me.rhunk.snapenhance.common.scripting.ktx.scriptable
import me.rhunk.snapenhance.common.scripting.ktx.scriptableObject
import me.rhunk.snapenhance.common.scripting.type.ModuleInfo
import org.mozilla.javascript.Function
@ -39,6 +40,7 @@ class JSModule(
putConst("info", this, scriptableObject {
putConst("name", this, moduleInfo.name)
putConst("version", this, moduleInfo.version)
putConst("displayName", this, moduleInfo.displayName)
putConst("description", this, moduleInfo.description)
putConst("author", this, moduleInfo.author)
putConst("minSnapchatVersion", this, moduleInfo.minSnapchatVersion)
@ -145,7 +147,16 @@ class JSModule(
moduleObject.putFunction("require") { args ->
val bindingName = args?.get(0).toString()
moduleBindings[bindingName]?.getObject()
val (namespace, path) = bindingName.takeIf {
it.startsWith("@") && it.contains("/")
}?.let {
it.substring(1).substringBefore("/") to it.substringAfter("/")
} ?: (null to "")
when (namespace) {
"modules" -> scriptRuntime.getModuleByName(path)?.moduleObject?.scriptable("module")?.scriptable("exports")
else -> moduleBindings[bindingName]?.getObject()
}
}
evaluateString(moduleObject, content, moduleInfo.name, 1, null)

View File

@ -54,12 +54,17 @@ open class ScriptRuntime(
}
return ModuleInfo(
name = properties["name"] ?: throw Exception("Missing module name"),
name = properties["name"]?.also {
if (!it.matches(Regex("[a-z_]+"))) {
throw Exception("Invalid module name : Only lowercase letters and underscores are allowed")
}
} ?: throw Exception("Missing module name"),
version = properties["version"] ?: throw Exception("Missing module version"),
displayName = properties["displayName"],
description = properties["description"],
author = properties["author"],
minSnapchatVersion = properties["minSnapchatVersion"]?.toLong(),
minSEVersion = properties["minSEVersion"]?.toLong(),
minSnapchatVersion = properties["minSnapchatVersion"]?.toLongOrNull(),
minSEVersion = properties["minSEVersion"]?.toLongOrNull(),
grantedPermissions = properties["permissions"]?.split(",")?.map { it.trim() } ?: emptyList(),
)
}

View File

@ -3,6 +3,7 @@ package me.rhunk.snapenhance.common.scripting.type
data class ModuleInfo(
val name: String,
val version: String,
val displayName: String? = null,
val description: String? = null,
val author: String? = null,
val minSnapchatVersion: Long? = null,

View File

@ -4,6 +4,7 @@ import me.rhunk.snapenhance.bridge.scripting.AutoReloadListener
import me.rhunk.snapenhance.bridge.scripting.IScripting
import me.rhunk.snapenhance.common.logger.AbstractLogger
import me.rhunk.snapenhance.common.scripting.ScriptRuntime
import me.rhunk.snapenhance.common.scripting.bindings.BindingSide
import me.rhunk.snapenhance.core.ModContext
import me.rhunk.snapenhance.core.scripting.impl.CoreIPC
import me.rhunk.snapenhance.core.scripting.impl.CoreScriptConfig
@ -17,6 +18,7 @@ class CoreScriptRuntime(
scripting = scriptingInterface
scriptingInterface.apply {
buildModuleObject = { module ->
putConst("currentSide", this, BindingSide.CORE.key)
module.registerBindings(
CoreScriptConfig(),
CoreIPC(),