From ce1e850c788edec6110d731fc9dccdac5143e683 Mon Sep 17 00:00:00 2001 From: WhiteChi Date: Fri, 10 Nov 2023 20:25:07 +0800 Subject: [PATCH] =?UTF-8?q?`Shamrock`:=20=E9=80=A3=E7=B5=90=E8=BB=A2?= =?UTF-8?q?=E9=80=81=E3=81=AE=E3=82=B5=E3=83=9D=E3=83=BC=E3=83=88=EF=BC=88?= =?UTF-8?q?=E5=8E=BB=E5=8B=A2=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../fuqiuluo/qqinterface/servlet/TicketSvc.kt | 4 + .../shamrock/remote/action/ActionManager.kt | 2 +- .../action/handlers/SendGroupForwardMsg.kt | 24 ++-- .../action/handlers/SendPrivateForwardMsg.kt | 125 ++++++++++++++++++ .../shamrock/remote/api/MessageAction.kt | 12 ++ .../remote/service/listener/AioListener.kt | 2 + 6 files changed, 160 insertions(+), 9 deletions(-) create mode 100644 xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateForwardMsg.kt diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt index 7b2384d..39f21ca 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/TicketSvc.kt @@ -43,6 +43,10 @@ internal object TicketSvc: BaseSvc() { return app.currentUin.ifBlank { "0" } } + fun getLongUin(): Long { + return app.longAccountUin + } + fun getCookie(): String { val uin = getUin() val skey = getRealSkey(uin) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt index 1762f7f..1fc59b3 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/ActionManager.kt @@ -33,7 +33,7 @@ internal object ActionManager { // MSG ACTIONS SendMessage, DeleteMessage, GetMsg, GetForwardMsg, SendGroupForwardMsg, SendGroupMessage, SendPrivateMessage, - ClearMsgs, GetHistoryMsg, GetGroupMsgHistory, + ClearMsgs, GetHistoryMsg, GetGroupMsgHistory, SendPrivateForwardMsg, // RESOURCE ACTION GetRecord, GetImage, UploadGroupFile, CreateGroupFileFolder, DeleteGroupFolder, diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendGroupForwardMsg.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendGroupForwardMsg.kt index c9ebe18..0a87768 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendGroupForwardMsg.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendGroupForwardMsg.kt @@ -18,6 +18,7 @@ import moe.fuqiuluo.shamrock.tools.EmptyJsonString import moe.fuqiuluo.shamrock.tools.asInt import moe.fuqiuluo.shamrock.tools.asJsonObject import moe.fuqiuluo.shamrock.tools.asString +import moe.fuqiuluo.shamrock.tools.asStringOrNull import moe.fuqiuluo.shamrock.tools.json import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher @@ -43,10 +44,13 @@ internal object SendGroupForwardMsg: IActionHandler() { val selfUin = TicketSvc.getUin() val msgs = message.map { - it.asJsonObject["data"].asJsonObject.let { - if (it.containsKey("content")) - MessageNode(it["name"].asString, it["content"]) - else MessageIdNode(it["id"].asInt) + it.asJsonObject["data"].asJsonObject.let { data -> + if (data.containsKey("content")) + MessageNode( + name = data["name"].asStringOrNull ?: "", + content = data["content"] + ) + else MessageIdNode(data["id"].asInt) } }.map { if (it is MessageIdNode) { @@ -72,14 +76,18 @@ internal object SendGroupForwardMsg: IActionHandler() { it.content != null } - var forwardMsgCallback: (() -> Unit)? = null + lateinit var forwardMsgCallback: (() -> Unit) val availableMsgSize = atomic(0) val msgIds = msgs.map { it.name to MessageHelper.sendMessageWithMsgId(MsgConstant.KCHATTYPEC2C, selfUin, it.content!!.let { msg -> if (msg is JsonArray) msg else MessageHelper.decodeCQCode(msg.asString) - }, { _, _ -> + }, { code, why -> + if (code != 0) { + availableMsgSize.incrementAndGet() + LogCenter.log("合并转发消息节点消息发送失败:$code($why)", Level.WARN) + } if (availableMsgSize.incrementAndGet() == msgs.size) { - forwardMsgCallback?.invoke() + forwardMsgCallback.invoke() } }).first } @@ -87,7 +95,7 @@ internal object SendGroupForwardMsg: IActionHandler() { val from = MessageHelper.generateContact(MsgConstant.KCHATTYPEC2C, selfUin) val to = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId) forwardMsgCallback = { - msgService.multiForwardMsg(ArrayList(msgIds.size).apply { + msgService.multiForwardMsg(ArrayList().apply { msgIds.forEach { add(MultiMsgInfo(it.second, it.first)) } }.also { it.reverse() }, from, to) { code, why -> if (code != 0) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateForwardMsg.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateForwardMsg.kt new file mode 100644 index 0000000..d641918 --- /dev/null +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateForwardMsg.kt @@ -0,0 +1,125 @@ +package moe.fuqiuluo.shamrock.remote.action.handlers + +import com.tencent.qqnt.kernel.nativeinterface.MsgConstant +import com.tencent.qqnt.kernel.nativeinterface.MultiMsgInfo +import kotlinx.atomicfu.atomic +import kotlinx.serialization.json.JsonArray +import kotlinx.serialization.json.JsonElement +import moe.fuqiuluo.qqinterface.servlet.MsgSvc +import moe.fuqiuluo.shamrock.remote.action.ActionSession +import moe.fuqiuluo.shamrock.remote.action.IActionHandler +import moe.fuqiuluo.qqinterface.servlet.TicketSvc +import moe.fuqiuluo.qqinterface.servlet.msg.convert.toSegments +import moe.fuqiuluo.shamrock.helper.Level +import moe.fuqiuluo.shamrock.helper.LogCenter +import moe.fuqiuluo.shamrock.helper.MessageHelper +import moe.fuqiuluo.shamrock.tools.EmptyJsonObject +import moe.fuqiuluo.shamrock.tools.EmptyJsonString +import moe.fuqiuluo.shamrock.tools.asInt +import moe.fuqiuluo.shamrock.tools.asJsonObject +import moe.fuqiuluo.shamrock.tools.asString +import moe.fuqiuluo.shamrock.tools.asStringOrNull +import moe.fuqiuluo.shamrock.tools.json +import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher + +internal object SendPrivateForwardMsg: IActionHandler() { + override suspend fun internalHandle(session: ActionSession): String { + val groupId = session.getString("user_id") + if (session.isArray("messages")) { + val messages = session.getArray("messages") + return invoke(messages, groupId, session.echo) + } + return logic("未知格式合并转发消息", session.echo) + } + + suspend operator fun invoke( + message: JsonArray, + userId: String, + echo: JsonElement = EmptyJsonString + ): String { + kotlin.runCatching { + val kernelService = NTServiceFetcher.kernelService + val sessionService = kernelService.wrapperSession + val msgService = sessionService.msgService + val selfUin = TicketSvc.getUin() + + val msgs = message.map { + it.asJsonObject["data"].asJsonObject.let { data -> + if (data.containsKey("content")) + MessageNode( + name = data["name"].asStringOrNull ?: "", + content = data["content"] + ) + else MessageIdNode(data["id"].asInt) + } + }.map { + if (it is MessageIdNode) { + val recordResult = MsgSvc.getMsg(it.id) + if (recordResult.isFailure) { + EmptyNode + } else { + val record = recordResult.getOrThrow() + MessageNode( + name = record.sendMemberName + .ifBlank { record.sendNickName } + .ifBlank { record.sendRemarkName } + .ifBlank { record.peerName }, + content = record.toSegments().map { segment -> + segment.toJson() + }.json + ) + } + } else { + it as MessageNode + } + }.filter { + it.content != null + } + + lateinit var forwardMsgCallback: (() -> Unit) + val availableMsgSize = atomic(0) + val msgIds = msgs.map { + it.name to MessageHelper.sendMessageWithMsgId(MsgConstant.KCHATTYPEC2C, selfUin, it.content!!.let { msg -> + if (msg is JsonArray) msg else MessageHelper.decodeCQCode(msg.asString) + }, { code, why -> + if (code != 0) { + availableMsgSize.incrementAndGet() + LogCenter.log("合并转发消息节点消息发送失败:$code($why)", Level.WARN) + } + if (availableMsgSize.incrementAndGet() == msgs.size) { + forwardMsgCallback.invoke() + } + }).first + } + + val from = MessageHelper.generateContact(MsgConstant.KCHATTYPEC2C, selfUin) + val to = MessageHelper.generateContact(MsgConstant.KCHATTYPEC2C, userId) + forwardMsgCallback = { + msgService.multiForwardMsg(ArrayList().apply { + msgIds.forEach { add(MultiMsgInfo(it.second, it.first)) } + }.also { it.reverse() }, from, to) { code, why -> + if (code != 0) + LogCenter.log("合并转发消息:$code($why)", Level.WARN) + } + } + return ok(data = EmptyJsonObject, echo = echo) + }.onFailure { + return error("error: $it", echo) + } + return logic("合并转发消息失败(unknown error)", echo) + } + + override val requiredParams: Array = arrayOf("user_id") + + override fun path(): String = "send_private_forward_msg" + + class MessageIdNode( + val id: Int + ): Node + open class MessageNode( + val name: String, + val content: JsonElement? + ): Node + object EmptyNode: MessageNode("", null) + interface Node +} \ No newline at end of file diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt index 2efd95c..9fdfd29 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/MessageAction.kt @@ -22,6 +22,18 @@ import moe.fuqiuluo.shamrock.tools.isJsonData import moe.fuqiuluo.shamrock.tools.isJsonString fun Routing.messageAction() { + post("/send_group_forward_msg") { + val groupId = fetchPostOrNull("group_id") + val messages = fetchPostJsonArray("messages") + call.respondText(SendGroupForwardMsg(messages, groupId ?: "")) + } + + post("/send_private_forward_msg") { + val userId = fetchPostOrNull("user_id") + val messages = fetchPostJsonArray("messages") + call.respondText(SendPrivateForwardMsg(messages, userId ?: "")) + } + getOrPost("/get_forward_msg") { val id = fetchOrThrow("id") call.respondText(GetForwardMsg(id)) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/listener/AioListener.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/listener/AioListener.kt index ee9e573..342f2bd 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/listener/AioListener.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/service/listener/AioListener.kt @@ -6,6 +6,7 @@ import com.tencent.qqnt.kernel.nativeinterface.* import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.launch +import moe.fuqiuluo.qqinterface.servlet.TicketSvc import moe.fuqiuluo.qqinterface.servlet.msg.convert.toCQCode import moe.fuqiuluo.qqinterface.servlet.transfile.RichProtoSvc import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig @@ -119,6 +120,7 @@ internal object AioListener: IKernelMsgListener { override fun onAddSendMsg(record: MsgRecord) { if (record.chatType == MsgConstant.KCHATTYPEGUILD) return // TODO: 频道消息暂不处理 + if (record.peerUin == TicketSvc.getLongUin()) return // 发给自己的消息不处理 GlobalScope.launch { try {