在3.3.0版本以上(alpha)添加了对cloudflare worker部署的支持, 通过Kotlin/JS将Kotlin代码编译为js代码, 并使用Worker的Websocket API来接受websocket请求, 此版本仍处于早期开发中, 可能会有很多的Bug, 请勿在正式环境中部署你的机器人.
开始前的准备
你需要安装wrangler来在本地运行你的worker程序
开始开发
在项目根目录创建一个wrangler.toml并按照wrangler.toml 配置修改部分信息。
添加以下gradle任务到build.gradle.kts中
val wranglerRunDir: Provider<Directory> = layout.buildDirectory.dir("wrangler-run")
tasks.register<Copy>("prepareWranglerRun") {
group = "wrangler"
dependsOn("compileDevelopmentExecutableKotlinJs")
val buildOutputDir = layout.buildDirectory.dir("compileSync/js/main/developmentExecutable/kotlin")
from(buildOutputDir)
into(wranglerRunDir)
}
val wranglerDev by tasks.registering(Exec::class) {
group = "wrangler"
workingDir = layout.buildDirectory.dir("wrangler-run").get().asFile.apply { mkdirs() }
doFirst {
val sourceDir = project.layout.projectDirectory
mapOf(
sourceDir.file("wrangler.toml").asFile to File(workingDir, "wrangler.toml"),
sourceDir.file(".dev.vars").asFile to File(workingDir, ".dev.vars"),
).forEach { (s, d) -> s.copyTo(d, overwrite = true) }
}
commandLine(
if (System.getProperty("os.name").lowercase().contains("windows")) listOf(
"cmd", "/c", "wrangler dev --port 7071"
)
else listOf("sh", "-c", "wrangler dev --port 7071")
)
standardInput = System.`in`
isIgnoreExitValue = false
}
val wranglerDeployDir: Provider<Directory> = layout.buildDirectory.dir("wrangler-deploy")
.apply { get().asFile.deleteRecursively() }
val prepareProductionDeploy by tasks.registering(Copy::class) {
group = "wrangler"
dependsOn("compileProductionExecutableKotlinJs")
val buildOutputDir = layout.buildDirectory.dir("compileSync/js/main/productionExecutable/kotlin")
from(buildOutputDir) { exclude("*.map") }
into(wranglerDeployDir)
from(layout.projectDirectory.file("wrangler.toml"))
into(wranglerDeployDir)
}
val wranglerDeploy by tasks.registering(Exec::class) {
group = "wrangler"
dependsOn(prepareProductionDeploy)
workingDir = layout.buildDirectory.dir("wrangler-deploy").get().asFile.apply { mkdirs() }
commandLine(
if (System.getProperty("os.name").lowercase().contains("windows")) listOf("cmd", "/c", "wrangler deploy")
else listOf("sh", "-c", "wrangler deploy")
)
standardInput = System.`in`
}这些任务可以快速帮助你运行/开发/部署
编写代码
/**
* 不要修改这个函数的任何内容
*/
fun main() {
@Suppress("unused_expression")
val eventListener = EventListener { event ->
val dyn = event.asDynamic()
event.asDynamic().respondWith(handleRequest(dyn.request as Request))
Unit
}
js("addEventListener('fetch', eventListener)")
}
/**
* 在这里使用createWorkerBot特殊方法创建Bot后
* 其余使用方法和常规ROB一致
*/
@JsExport
fun handleRequest(request: Request): Promise<Response> = GlobalScope.promise {
OneBotFactory.createWorkerBot("a-secret-access-token", object : OneBotListener {
override suspend fun onGroupMessage(message: GroupMessage) {
if (message.text.contains("Hi")) {
message.reply("Hello")
}
}
})
return@promise workerApplication.handle(request)
}运行程序
在IntelliJ IDEA右侧Gradle任务窗口找到wrangler组, 首先运行prepareWranglerRun,再运行wranglerDev, 不要停止或重新运行wranglerDev任务, 这是一个后台任务wrangler会自动热重载代码, 需要重新运行程序时你需要 运行prepareWranglerRun任务
启动一个OneBot11实现并支持反向Websocket, 将地址填写为wrangler的地址并配置accessToken,
部署程序
你需要先手动执行wrangler login命令来登录到cloudflare, 之后运行prepareProductionDeploy等待执行完毕后运行 wranglerDeploy任务
注意事项
需要注意的是Cloudflare worker并不是一个标准的nodejs环境也不是一个浏览器环境而是V8运行时, 并且一些常规的API使用方法均有不同, rob-worker-js依赖于 kotlin-cloudflare-worker, 这是一个由我开发的纯Kotlin实现的cloudflare worker兼容层库,内置了一些常用的函数,例如: http客户端 websocket服务器, 你可以前往kotlin-cloudflare-worker 来查看具体用法和具体注意事项
Worker限制了CPU时间如果需要执行CPU密集型任务请考虑优化你的代码逻辑
创建协程作用域
请使用GlobalScope.promose {}或MainScope().launch {}来创建一个协程作用域, 不要使用CoroutineScope(Dispatcher.Default).launch {}创建协程作用域, 因为使用此方法创建的所有协程 都会被drop不会被执行