diff --git a/qqinterface/src/main/java/com/tencent/mobileqq/troop/api/ITroopMemberNameService.java b/qqinterface/src/main/java/com/tencent/mobileqq/troop/api/ITroopMemberNameService.java new file mode 100644 index 0000000..52f365f --- /dev/null +++ b/qqinterface/src/main/java/com/tencent/mobileqq/troop/api/ITroopMemberNameService.java @@ -0,0 +1,28 @@ +package com.tencent.mobileqq.troop.api; + +import mqq.app.api.IRuntimeService; +import com.tencent.mobileqq.data.troop.TroopMemberInfo; + +public interface ITroopMemberNameService extends IRuntimeService { + String getTroopMemberColorNick(String str, String str2); + + String getTroopMemberName(TroopMemberInfo troopMemberInfo); + + String getTroopMemberName(String str, String str2); + + String getTroopMemberName(String str, String str2, String str3, String str4); + + String getTroopMemberName(String str, String str2, boolean z, boolean z2); + + //void getTroopMemberNameAsync(String str, String str2, a aVar); + + String getTroopMemberNameInUI(String str, String str2); + + String getTroopMemberNameRemarkFirst(String str, String str2); + + String getTroopMemberNameWithoutRemark(String str, String str2); + + String getTroopMemberNick(String str, String str2); + + String getTroopMemberNickByTroopCode(String str, String str2); +} \ No newline at end of file diff --git a/qqinterface/src/main/java/com/tencent/qqnt/kernel/api/impl/MsgService.java b/qqinterface/src/main/java/com/tencent/qqnt/kernel/api/impl/MsgService.java index a48bbb7..0b344e3 100644 --- a/qqinterface/src/main/java/com/tencent/qqnt/kernel/api/impl/MsgService.java +++ b/qqinterface/src/main/java/com/tencent/qqnt/kernel/api/impl/MsgService.java @@ -1,7 +1,9 @@ package com.tencent.qqnt.kernel.api.impl; import com.tencent.qqnt.kernel.nativeinterface.IKernelMsgListener; +import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback; import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo; +import com.tencent.qqnt.kernel.nativeinterface.TempChatPrepareInfo; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -18,4 +20,8 @@ public class MsgService { public String getRichMediaFilePathForMobileQQSend(@NotNull RichMediaFilePathInfo richMediaFilePathInfo) { return null; } + + public void prepareTempChat(TempChatPrepareInfo tempChatPrepareInfo, IOperateCallback cb) { + + } } diff --git a/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/TempChatPrepareInfo.java b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/TempChatPrepareInfo.java index 7d04dd0..84b8b36 100644 --- a/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/TempChatPrepareInfo.java +++ b/qqinterface/src/main/java/com/tencent/qqnt/kernel/nativeinterface/TempChatPrepareInfo.java @@ -56,20 +56,14 @@ public final class TempChatPrepareInfo { return "TempChatPrepareInfo{chatType=" + this.chatType + ",peerUid=" + this.peerUid + ",peerNickname=" + this.peerNickname + ",fromGroupCode=" + this.fromGroupCode + ",sig=" + this.sig + ",selfUid=" + this.selfUid + ",selfPhone=" + this.selfPhone + ",gameSession=" + this.gameSession + ",}"; } - public TempChatPrepareInfo(int i2, String str, String str2, String str3, byte[] bArr, String str4, String str5, TempChatGameSession tempChatGameSession) { - this.peerUid = ""; - this.peerNickname = ""; - this.fromGroupCode = ""; - this.sig = new byte[0]; - this.selfUid = ""; - this.selfPhone = ""; - this.chatType = i2; - this.peerUid = str; - this.peerNickname = str2; - this.fromGroupCode = str3; - this.sig = bArr; - this.selfUid = str4; - this.selfPhone = str5; - this.gameSession = tempChatGameSession; + public TempChatPrepareInfo(int chatType, String peerId, String nickName, String fromGroup, byte[] sig, String selfUid, String selfPhone, TempChatGameSession session) { + this.chatType = chatType; + this.peerUid = peerId; + this.peerNickname = nickName; + this.fromGroupCode = fromGroup; + this.sig = sig; + this.selfUid = selfUid; + this.selfPhone = selfPhone; + this.gameSession = session; } } diff --git a/qqinterface/src/main/java/mqq/app/AppRuntime.java b/qqinterface/src/main/java/mqq/app/AppRuntime.java index 459c83c..fc8d304 100644 --- a/qqinterface/src/main/java/mqq/app/AppRuntime.java +++ b/qqinterface/src/main/java/mqq/app/AppRuntime.java @@ -81,6 +81,10 @@ public abstract class AppRuntime { return !"0".equals(getCurrentAccountUin()) ? getCurrentAccountUin() : ""; } + public String getCurrentUid() { + return ""; + } + public long getLongAccountUin() { return 0; } diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/MsgSvc.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/MsgSvc.kt index 397cef0..4bdcc93 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/MsgSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/MsgSvc.kt @@ -1,15 +1,24 @@ package moe.fuqiuluo.qqinterface.servlet import com.tencent.mobileqq.qroute.QRoute +import com.tencent.mobileqq.troop.api.ITroopMemberNameService +import com.tencent.qqnt.kernel.api.IKernelService import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback +import com.tencent.qqnt.kernel.nativeinterface.MsgConstant import com.tencent.qqnt.kernel.nativeinterface.MsgRecord +import com.tencent.qqnt.kernel.nativeinterface.TempChatGameSession +import com.tencent.qqnt.kernel.nativeinterface.TempChatPrepareInfo import com.tencent.qqnt.msg.api.IMsgService import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.withTimeoutOrNull import kotlinx.serialization.json.JsonArray -import moe.fuqiuluo.shamrock.helper.MessageHelper +import moe.fuqiuluo.shamrock.helper.ContactHelper +import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.LogCenter +import moe.fuqiuluo.shamrock.helper.MessageHelper +import moe.fuqiuluo.shamrock.tools.EMPTY_BYTE_ARRAY import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher +import moe.fuqiuluo.shamrock.xposed.helper.msgService import kotlin.coroutines.resume import kotlin.coroutines.suspendCoroutine @@ -18,6 +27,27 @@ internal object MsgSvc: BaseSvc() { return Result.failure(Exception("Not implemented")) } + suspend fun prepareTempChatFromGroup( + groupId: String, + peerId: String + ): Result { + LogCenter.log("主动临时消息,创建临时会话。", Level.INFO) + val msgService = app.getRuntimeService(IKernelService::class.java, "all").msgService + ?: return Result.failure(Exception("获取消息服务失败")) + msgService.prepareTempChat(TempChatPrepareInfo( + MsgConstant.KCHATTYPETEMPC2CFROMGROUP, + ContactHelper.getUidByUinAsync(peerId = peerId.toLong()), + app.getRuntimeService(ITroopMemberNameService::class.java, "all") + .getTroopMemberNameRemarkFirst(groupId, peerId), + groupId, EMPTY_BYTE_ARRAY, app.currentUid, "", TempChatGameSession() + )) { code, reason -> + if (code != 0) { + LogCenter.log("临时会话创建失败: $code, $reason", Level.ERROR) + } + } + return Result.success(Unit) + } + /** * 正常获取 */ @@ -139,6 +169,17 @@ internal object MsgSvc: BaseSvc() { ): Pair { //LogCenter.log(message.toString(), Level.ERROR) //callback.msgHash = result.second 什么垃圾代码,万一cb比你快,你不就寄了? + + // 主动临时消息 + when(chatType) { + MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> { + prepareTempChatFromGroup(fromId, peedId).onFailure { + LogCenter.log("主动临时消息,创建临时会话失败。", Level.ERROR) + return -1L to 0 + } + } + } + return MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, MessageCallback(peedId, 0), fromId) } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/helper/MessageHelper.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/helper/MessageHelper.kt index 43d4322..6d8fff8 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/helper/MessageHelper.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/helper/MessageHelper.kt @@ -44,6 +44,7 @@ internal object MessageHelper { if(callback is MsgSvc.MessageCallback) { callback.msgHash = uniseq.first } + service.sendMsg( generateContact(chatType, peerId, fromId), uniseq.second, diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendMessage.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendMessage.kt index 0b38a47..17ce283 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendMessage.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendMessage.kt @@ -81,10 +81,13 @@ internal object SendMessage: IActionHandler() { MsgSvc.sendToAio(chatType, peerId, msg, fromId = fromId) } } + if (result.first <= 0) { + return logic("send message failed", echo = echo) + } return ok(MessageResult( msgId = result.second, time = result.first * 0.001 - ), echo) + ), echo = echo) } // 消息段格式消息 @@ -95,6 +98,9 @@ internal object SendMessage: IActionHandler() { // return logic("contact is not found", echo = echo) //} val result = MsgSvc.sendToAio(chatType, peerId, message, fromId = fromId) + if (result.first <= 0) { + return logic("send message failed", echo = echo) + } return ok(MessageResult( msgId = result.second, time = result.first * 0.001 diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateMessage.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateMessage.kt index 86137d0..0d03a33 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateMessage.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/action/handlers/SendPrivateMessage.kt @@ -12,10 +12,23 @@ internal object SendPrivateMessage: IActionHandler() { return if (session.isString("message")) { val autoEscape = session.getBooleanOrDefault("auto_escape", false) val message = session.getString("message") - SendMessage(chatTYpe, userId, message, autoEscape, echo = session.echo, fromId = groupId ?: userId) + SendMessage.invoke( + chatType = chatTYpe, + peerId = userId, + message = message, + autoEscape = autoEscape, + echo = session.echo, + fromId = groupId ?: userId + ) } else { val message = session.getArray("message") - SendMessage(chatTYpe, userId, message, session.echo, fromId = groupId ?: userId) + SendMessage( + chatType = chatTYpe, + peerId = userId, + message = message, + echo = session.echo, + fromId = groupId ?: userId + ) } } 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 4126ae5..a794522 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 @@ -42,13 +42,13 @@ fun Routing.messageAction() { } post { val msgType = fetchPostOrThrow("message_type") - val peerIdKey = if(msgType == "group") "group_id" else "user_id" val chatType = MessageHelper.obtainMessageTypeByDetailType(msgType) + val peerId = fetchPostOrThrow(if(msgType == "group") "group_id" else "user_id") call.respondText(if (isJsonData() && !isJsonString("message")) { - SendMessage(chatType, fetchPostOrThrow(peerIdKey), fetchPostJsonArray("message")) + SendMessage(chatType, peerId, fetchPostJsonArray("message")) } else { val autoEscape = fetchPostOrNull("auto_escape")?.toBooleanStrict() ?: false - SendMessage(chatType, fetchPostOrThrow(peerIdKey), fetchPostOrThrow("message"), autoEscape) + SendMessage(chatType, peerId, fetchPostOrThrow("message"), autoEscape) }) } } diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/KtorServer.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/KtorServer.kt index 4fe8b79..9a1fad8 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/KtorServer.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/tools/KtorServer.kt @@ -25,6 +25,8 @@ import io.ktor.http.parseUrlEncodedParameters import io.ktor.server.request.httpMethod import io.ktor.server.routing.route import kotlinx.serialization.json.JsonElement +import moe.fuqiuluo.shamrock.helper.Level +import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.remote.entries.CommonResult import moe.fuqiuluo.shamrock.remote.entries.EmptyObject import moe.fuqiuluo.shamrock.remote.entries.Status @@ -88,7 +90,7 @@ suspend fun ApplicationCall.fetchPostOrThrow(key: String): String { } fun ApplicationCall.isJsonData(): Boolean { - return ContentType.Application.Json == request.contentType() + return ContentType.Application.Json == request.contentType() || ContentType.Application.ProblemJson == request.contentType() } suspend fun ApplicationCall.fetchPostOrNull(key: String): String? { @@ -102,6 +104,7 @@ suspend fun ApplicationCall.fetchPostOrNull(key: String): String? { if (isJsonData()) { Json.parseToJsonElement(receiveText()).jsonObject.also { attributes.put(jsonKey, it) + attributes.put(isJsonKey, true) }[key].asStringOrNull } else if ( ContentType.Application.FormUrlEncoded == request.contentType() @@ -113,7 +116,7 @@ suspend fun ApplicationCall.fetchPostOrNull(key: String): String? { receiveTextAsUnknown(key) } }.getOrElse { - receiveTextAsUnknown(key) + throw IllegalArgumentException("JSON数据格式不合法") } } @@ -177,6 +180,7 @@ suspend fun PipelineContext.isJsonString(key: String): Bo } else { Json.parseToJsonElement(call.receiveText()).jsonObject.also { call.attributes.put(jsonKey, it) + call.attributes.put(isJsonKey, true) } } return data[key] is JsonPrimitive @@ -245,6 +249,7 @@ suspend fun PipelineContext.fetchPostJsonArray(key: Strin } else { Json.parseToJsonElement(call.receiveText()).jsonObject.also { call.attributes.put(jsonKey, it) + call.attributes.put(isJsonKey, true) } } return data[key].asJsonArray