From 4adf2eb84a4dfd7c0043153b17bbad1b921c56c9 Mon Sep 17 00:00:00 2001 From: WhiteChi Date: Tue, 31 Oct 2023 00:19:51 +0800 Subject: [PATCH] =?UTF-8?q?`Shamrock`:=20=E3=83=97=E3=83=AD=E3=83=95?= =?UTF-8?q?=E3=82=A1=E3=82=A4=E3=83=AB=E3=83=AD=E3=82=B8=E3=83=83=E3=82=AF?= =?UTF-8?q?=E3=81=AE=E5=A4=89=E6=9B=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: WhiteChi --- .../shamrock/ui/fragment/LabFragment.kt | 3 +- xposed/build.gradle.kts | 5 +- .../remote/service/WebSocketService.kt | 5 +- .../shamrock/remote/service/config/Config.kt | 17 ++++- .../remote/service/config/ShamrockConfig.kt | 74 +++++++++---------- .../java/moe/fuqiuluo/shamrock/tools/Json.kt | 10 +++ .../xposed/actions/InitRemoteService.kt | 38 +++++----- 7 files changed, 88 insertions(+), 64 deletions(-) diff --git a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt index 4789c72..cb47a92 100644 --- a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt +++ b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/LabFragment.kt @@ -180,6 +180,7 @@ fun LabFragment() { return@Function true } + /* Function( title = "使用纯数字ECHO", desc = "在部分强类型语言框架,需要打开此开关。", @@ -189,7 +190,7 @@ fun LabFragment() { ShamrockConfig.setEchoNumber(ctx, it) ShamrockConfig.pushUpdate(ctx) return@Function true - } + }*/ } } } diff --git a/xposed/build.gradle.kts b/xposed/build.gradle.kts index daf0833..56af105 100644 --- a/xposed/build.gradle.kts +++ b/xposed/build.gradle.kts @@ -3,7 +3,7 @@ plugins { id("org.jetbrains.kotlin.android") //id("io.realm.kotlin") id("kotlin-kapt") - kotlin("plugin.serialization") version "1.8.0" + kotlin("plugin.serialization") version "1.8.10" } android { @@ -59,7 +59,8 @@ dependencies { //implementation("io.realm.kotlin:library-sync:1.11.0") val ktorVersion = "2.3.3" - implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") + //implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.1") + implementation("io.github.xn32:json5k:0.3.0") implementation("org.jetbrains.kotlinx:kotlinx-io-jvm:0.1.16") implementation("io.ktor:ktor-server-core:$ktorVersion") implementation("io.ktor:ktor-server-host-common:$ktorVersion") diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/WebSocketService.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/WebSocketService.kt index cca9956..7599b48 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/WebSocketService.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/WebSocketService.kt @@ -51,7 +51,7 @@ internal class WebSocketService(port: Int): WebSocketTransmitServlet(port) { } override fun onOpen(conn: WebSocket, handshake: ClientHandshake) { - val token = ShamrockConfig.getToken() + val token = ShamrockConfig.getActiveWebSocketConfig()?.token ?: ShamrockConfig.getToken() if (token.isNotBlank()) { var accessToken = handshake.getFieldValue("access_token") .ifNullOrEmpty(handshake.getFieldValue("ticket")) @@ -60,7 +60,8 @@ internal class WebSocketService(port: Int): WebSocketTransmitServlet(port) { if (accessToken.startsWith("Bearer ")) { accessToken = accessToken.substring(7) } - if (token != accessToken) { + val tokenList = token.split(",", "|", ",") + if (!tokenList.contains(accessToken)) { conn.close() LogCenter.log({ "WSServer连接错误(${conn.remoteSocketAddress.address.hostAddress}:${conn.remoteSocketAddress.port}) 没有提供正确的token, $accessToken。" }, Level.ERROR) return diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/Config.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/Config.kt index 673b5a9..a560cb1 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/Config.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/Config.kt @@ -5,8 +5,23 @@ import kotlinx.serialization.Serializable @Serializable data class ServiceConfig( + @SerialName("rules") val rules: Rules? = null, + @SerialName("default_token") var defaultToken: String? = null, + @SerialName("active_websocket") var activeWebSocket: ConnectionConfig? = null, + @SerialName("passive_websocket") var passiveWebSocket: MutableList? = null, +) + +@Serializable +data class ConnectionConfig( + @SerialName("address") val address: String? = null, + @SerialName("port") var port: Int? = null, + @SerialName("token") val token: String? = null, +) + +@Serializable +data class Rules( @SerialName("group_rule") val groupRule: GroupRule? = null, - @SerialName("private_rule") val privateRule: PrivateRule? = null, + @SerialName("private_rule") val privateRule: PrivateRule? = null ) @Serializable diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/ShamrockConfig.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/ShamrockConfig.kt index 5019413..311163e 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/ShamrockConfig.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/config/ShamrockConfig.kt @@ -1,7 +1,9 @@ package moe.fuqiuluo.shamrock.remote.service.config import android.content.Intent -import moe.fuqiuluo.shamrock.tools.GlobalJson +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.encodeToString +import moe.fuqiuluo.shamrock.tools.GlobalJson5 import moe.fuqiuluo.shamrock.utils.MMKVFetcher import mqq.app.MobileQQ import java.io.File @@ -12,35 +14,51 @@ internal object ShamrockConfig { if (it.exists()) it.delete() it.mkdirs() } - private val Config by lazy { - GlobalJson.decodeFromString(ConfigDir.resolve("config.json").also { + private val Config: ServiceConfig + get() = GlobalJson5.decodeFromString(ConfigDir.resolve("config.json").also { if (!it.exists()) it.writeText("{}") }.readText()) - } fun isInit(): Boolean { val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") return mmkv.getBoolean("isInit", false) } + fun updateConfig(config: ServiceConfig = Config) { + ConfigDir.resolve("config.json").writeText(GlobalJson5.encodeToString(config)) + } + fun updateConfig(intent: Intent) { val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") mmkv.apply { putBoolean( "tablet", intent.getBooleanExtra("tablet", false)) // 强制平板模式 putInt( "port", intent.getIntExtra("port", 5700)) // 主动HTTP端口 putBoolean( "ws", intent.getBooleanExtra("ws", false)) // 主动WS开关 - putInt( "ws_port", intent.getIntExtra("ws_port", 5800)) // 主动WS端口 putBoolean( "http", intent.getBooleanExtra("http", false)) // HTTP回调开关 putString( "http_addr", intent.getStringExtra("http_addr")) // WebHook回调地址 putBoolean( "ws_client", intent.getBooleanExtra("ws_client", false)) // 被动WS开关 putBoolean( "use_cqcode", intent.getBooleanExtra("use_cqcode", false)) // 使用CQ码 - putString( "ws_addr", intent.getStringExtra("ws_addr")) // 被动WS地址 - putBoolean( "pro_api", intent.getBooleanExtra("pro_api", false)) // 开发调试API开关 putBoolean( "inject_packet", intent.getBooleanExtra("inject_packet", false)) // 拦截无用包 putBoolean( "debug", intent.getBooleanExtra("debug", false)) // 调试模式 - putString( "token", intent.getStringExtra("token")) // 鉴权 - // 接收ssl配置 + Config.defaultToken = intent.getStringExtra("token") + + val wsPort = intent.getIntExtra("ws_port", 5800) + Config.activeWebSocket = if (Config.activeWebSocket == null) ConnectionConfig( + address = "0.0.0.0", + port = wsPort, + ) else Config.activeWebSocket?.also { + it.port = wsPort + } + + Config.passiveWebSocket = intent.getStringExtra("ws_addr")?.split(",", "|", ",")?.filter { address -> + Config.passiveWebSocket?.any { + it.address == address + } == false + }?.map { + ConnectionConfig(address = it) + }?.toMutableList() + putString( "key_store", intent.getStringExtra("key_store")) // 证书路径 putString( "ssl_pwd", intent.getStringExtra("ssl_pwd")) // 证书密码 putString( "ssl_private_pwd", intent.getStringExtra("ssl_private_pwd")) // 证书私钥密码 @@ -51,33 +69,19 @@ internal object ShamrockConfig { putBoolean("enable_self_msg", intent.getBooleanExtra("enable_self_msg", false)) // 推送自己发的消息 - putBoolean("echo_number", intent.getBooleanExtra("echo_number", false)) // 将echo格式化为数字输出 - putBoolean("isInit", true) } - } - - fun isEchoNumber(): Boolean { - val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") - return mmkv.getBoolean("echo_number", false) - } - - /** - * 忽略所有推送事件 - */ - fun isIgnoreAllEvent(): Boolean { - return false + updateConfig() } fun getGroupMsgRule(): GroupRule? { - return Config.groupRule + return Config.rules?.groupRule } fun getPrivateRule(): PrivateRule? { - return Config.privateRule + return Config.rules?.privateRule } - fun enableSelfMsg(): Boolean { val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") return mmkv.getBoolean("enable_self_msg", false) @@ -88,9 +92,8 @@ internal object ShamrockConfig { return mmkv.getBoolean("ws_client", false) } - fun getWebSocketClientAddress(): String { - val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") - return mmkv.getString("ws_addr", "") ?: "" + fun getWebSocketClientAddress(): List { + return Config.passiveWebSocket ?: emptyList() } fun openWebSocket(): Boolean { @@ -98,14 +101,12 @@ internal object ShamrockConfig { return mmkv.getBoolean("ws", false) } - fun getWebSocketPort(): Int { - val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") - return mmkv.getInt("ws_port", 5800) + fun getActiveWebSocketConfig(): ConnectionConfig? { + return Config.activeWebSocket } fun getToken(): String { - val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") - return mmkv.getString("token", "") ?: "" + return Config.defaultToken ?: "" } fun useCQ(): Boolean { @@ -133,11 +134,6 @@ internal object ShamrockConfig { return mmkv.getInt("port", 5700) } - fun isPro(): Boolean { - val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") - return mmkv.getBoolean("pro_api", false) - } - fun isInjectPacket(): Boolean { val mmkv = MMKVFetcher.mmkvWithId("shamrock_config") return mmkv.getBoolean("inject_packet", false) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/Json.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/Json.kt index 9407585..d236d33 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/Json.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/Json.kt @@ -1,5 +1,6 @@ package moe.fuqiuluo.shamrock.tools +import io.github.xn32.json5k.Json5 import kotlinx.serialization.json.Json import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonElement @@ -25,6 +26,15 @@ val GlobalJson = Json { coerceInputValues = true // 强制输入值 } + +val GlobalJson5 = Json5 { + prettyPrint = true + indentationWidth = 2 + useSingleQuotes = true + quoteMemberNames = true + encodeDefaults = true +} + val String.asJson: JsonElement get() = Json.parseToJsonElement(this) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt index 7e645c7..3946bab 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/xposed/actions/InitRemoteService.kt @@ -8,7 +8,6 @@ import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch import moe.fuqiuluo.shamrock.remote.service.WebSocketClientService import moe.fuqiuluo.shamrock.remote.service.WebSocketService -import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig import moe.fuqiuluo.shamrock.utils.PlatformUtils import moe.fuqiuluo.shamrock.helper.Level @@ -45,23 +44,24 @@ internal class InitRemoteService : IAction { if (ShamrockConfig.openWebSocketClient()) { val runtime = AppRuntimeFetcher.appRuntime val curUin = runtime.currentAccountUin - val wsHeaders = hashMapOf( - "X-Client-Role" to "Universal", - "X-Self-ID" to curUin, - "User-Agent" to "Shamrock/$ShamrockVersion", - "X-QQ-Version" to PlatformUtils.getClientVersion(MobileQQ.getContext()), - "X-OneBot-Version" to "11", - "X-Impl" to "Shamrock", - "Sec-WebSocket-Protocol" to "11.Shamrock" - ) - val token = ShamrockConfig.getToken() - if (token.isNotBlank()) { - wsHeaders["authorization"] = "bearer $token" - //wsHeaders["bearer"] = token - } - ShamrockConfig.getWebSocketClientAddress().split(",", "|", ",").forEach { url -> - if (url.isNotBlank()) - startWebSocketClient(url, wsHeaders) + val defaultToken = ShamrockConfig.getToken() + ShamrockConfig.getWebSocketClientAddress().forEach { conn -> + if (!conn.address.isNullOrBlank()) { + val token = conn.token ?: defaultToken + val wsHeaders = hashMapOf( + "X-Client-Role" to "Universal", + "X-Self-ID" to curUin, + "User-Agent" to "Shamrock/$ShamrockVersion", + "X-QQ-Version" to PlatformUtils.getClientVersion(MobileQQ.getContext()), + "X-OneBot-Version" to "11", + "X-Impl" to "Shamrock", + "Sec-WebSocket-Protocol" to "11.Shamrock" + ) + if (token.isNotBlank()) { + wsHeaders["authorization"] = "bearer $token" + } + startWebSocketClient(conn.address, wsHeaders) + } } } } @@ -69,7 +69,7 @@ internal class InitRemoteService : IAction { private fun startWebSocketServer() { GlobalScope.launch { try { - val server = WebSocketService(ShamrockConfig.getWebSocketPort()) + val server = WebSocketService(ShamrockConfig.getActiveWebSocketConfig()?.port ?: 5700) server.start() } catch (e: Throwable) { LogCenter.log(e.stackTraceToString(), Level.ERROR)