Shamrock: fix #109

This commit is contained in:
ikechan8370 2023-11-30 22:38:44 +08:00
parent 7d8772ebf6
commit 2fdcfe332b
3 changed files with 78 additions and 21 deletions

View File

@ -16,10 +16,8 @@ import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.time.withTimeoutOrNull
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import moe.fuqiuluo.proto.protobufOf
import moe.fuqiuluo.shamrock.helper.ContactHelper import moe.fuqiuluo.shamrock.helper.ContactHelper
import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.LogCenter
@ -174,22 +172,36 @@ internal object MsgSvc: BaseSvc() {
chatType: Int, chatType: Int,
peedId: String, peedId: String,
message: JsonArray, message: JsonArray,
fromId: String = peedId fromId: String = peedId,
): Pair<Long, Int> { retryCnt: Int = 3
): Result<Pair<Long, Int>> {
//LogCenter.log(message.toString(), Level.ERROR) //LogCenter.log(message.toString(), Level.ERROR)
//callback.msgHash = result.second 什么垃圾代码万一cb比你快你不就寄了 //callback.msgHash = result.second 什么垃圾代码万一cb比你快你不就寄了
// 主动临时消息 // 主动临时消息
when(chatType) { when (chatType) {
MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> { MsgConstant.KCHATTYPETEMPC2CFROMGROUP -> {
prepareTempChatFromGroup(fromId, peedId).onFailure { prepareTempChatFromGroup(fromId, peedId).onFailure {
LogCenter.log("主动临时消息,创建临时会话失败。", Level.ERROR) LogCenter.log("主动临时消息,创建临时会话失败。", Level.ERROR)
return -1L to 0 return Result.failure(Exception("主动临时消息,创建临时会话失败。"))
} }
} }
} }
val result = MessageHelper.sendMessageWithoutMsgId(
return MessageHelper.sendMessageWithoutMsgId(chatType, peedId, message, MessageCallback(peedId, 0), fromId) chatType,
peedId,
message,
fromId,
MessageCallback(peedId, 0)
)
return if (result.isFailure && retryCnt > 0) {
// 可能网络问题出现红色感叹号,重试
// 例如 rich media transfer failed
delay(100)
sendToAio(chatType, peedId, message, fromId, retryCnt - 1)
} else {
result
}
} }
suspend fun getMultiMsg(resId: String): Result<List<MsgRecord>> { suspend fun getMultiMsg(resId: String): Result<List<MsgRecord>> {

View File

@ -6,6 +6,10 @@ import com.tencent.qqnt.kernel.nativeinterface.IOperateCallback
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import com.tencent.qqnt.kernel.nativeinterface.MsgElement import com.tencent.qqnt.kernel.nativeinterface.MsgElement
import com.tencent.qqnt.msg.api.IMsgService import com.tencent.qqnt.msg.api.IMsgService
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.json.JsonArray import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.JsonElement import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
@ -20,6 +24,8 @@ import moe.fuqiuluo.shamrock.tools.asJsonObjectOrNull
import moe.fuqiuluo.shamrock.tools.asString import moe.fuqiuluo.shamrock.tools.asString
import moe.fuqiuluo.shamrock.tools.json import moe.fuqiuluo.shamrock.tools.json
import moe.fuqiuluo.shamrock.tools.jsonArray import moe.fuqiuluo.shamrock.tools.jsonArray
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine
import kotlin.math.abs import kotlin.math.abs
internal object MessageHelper { internal object MessageHelper {
@ -36,31 +42,62 @@ internal object MessageHelper {
}.second.filter { }.second.filter {
it.elementType != -1 it.elementType != -1
} as ArrayList<MsgElement> } as ArrayList<MsgElement>
return sendMessageWithoutMsgId(chatType, peerId, msg, callback, fromId) return sendMessageWithoutMsgId(chatType, peerId, msg, fromId, callback)
} }
@OptIn(DelicateCoroutinesApi::class)
suspend fun sendMessageWithoutMsgId( suspend fun sendMessageWithoutMsgId(
chatType: Int, chatType: Int,
peerId: String, peerId: String,
message: JsonArray, message: JsonArray,
callback: IOperateCallback, fromId: String = peerId,
fromId: String = peerId callback: IOperateCallback
): Pair<Long, Int> { ): Result<Pair<Long, Int>> {
val uniseq = generateMsgId(chatType) val uniseq = generateMsgId(chatType)
val msg = messageArrayToMessageElements(chatType, uniseq.second, peerId, message).also { val msg = messageArrayToMessageElements(chatType, uniseq.second, peerId, message).also {
if (it.second.isEmpty() && !it.first) error("消息合成失败,请查看日志或者检查输入。") if (it.second.isEmpty() && !it.first) error("消息合成失败,请查看日志或者检查输入。")
}.second.filter { }.second.filter {
it.elementType != -1 it.elementType != -1
} as ArrayList<MsgElement> } as ArrayList<MsgElement>
return sendMessageWithoutMsgId(chatType, peerId, msg, callback, fromId) val totalSize = msg.filter {
it.elementType == MsgConstant.KELEMTYPEPIC ||
it.elementType == MsgConstant.KELEMTYPEPTT ||
it.elementType == MsgConstant.KELEMTYPEVIDEO
}.map {
(it.picElement?.fileSize ?: 0) + (it.pttElement?.fileSize
?: 0) + (it.videoElement?.fileSize ?: 0)
}.reduceOrNull { a, b -> a + b } ?: 0
val estimateTime = (totalSize / (300 * 1024)) * 1000 + 5000
lateinit var sendResultPair: Pair<Long, Int>
val sendRet = withTimeoutOrNull<Pair<Int, String>>(estimateTime) {
suspendCoroutine {
GlobalScope.launch {
sendResultPair = sendMessageWithoutMsgId(
chatType,
peerId,
msg,
fromId
) { code, message ->
callback.onResult(code, message)
it.resume(code to message)
}
}
}
}
if (sendRet?.first != 0) {
return Result.failure(Exception(sendRet?.second ?: "发送消息超时"))
}
return Result.success(sendResultPair)
// return sendMessageWithoutMsgId(chatType, peerId, msg, fromId, callback)
} }
suspend fun sendMessageWithoutMsgId( suspend fun sendMessageWithoutMsgId(
chatType: Int, chatType: Int,
peerId: String, peerId: String,
message: ArrayList<MsgElement>, message: ArrayList<MsgElement>,
callback: IOperateCallback, fromId: String = peerId,
fromId: String = peerId callback: IOperateCallback
): Pair<Long, Int> { ): Pair<Long, Int> {
return sendMessageWithoutMsgId(generateContact(chatType, peerId, fromId), message, callback) return sendMessageWithoutMsgId(generateContact(chatType, peerId, fromId), message, callback)
} }

View File

@ -92,12 +92,16 @@ internal object SendMessage: IActionHandler() {
MsgSvc.sendToAio(chatType, peerId, msg, fromId = fromId) MsgSvc.sendToAio(chatType, peerId, msg, fromId = fromId)
} }
} }
if (result.first <= 0) { if (result.isFailure) {
return logic(result.exceptionOrNull()?.message ?: "", echo)
}
val pair = result.getOrNull() ?: Pair(0L, 0)
if (pair.first <= 0) {
return logic("send message failed", echo = echo) return logic("send message failed", echo = echo)
} }
return ok(MessageResult( return ok(MessageResult(
msgId = result.second, msgId = pair.second,
time = (result.first * 0.001).toLong() time = (pair.first * 0.001).toLong()
), echo = echo) ), echo = echo)
} }
@ -109,12 +113,16 @@ internal object SendMessage: IActionHandler() {
// return logic("contact is not found", echo = echo) // return logic("contact is not found", echo = echo)
//} //}
val result = MsgSvc.sendToAio(chatType, peerId, message, fromId = fromId) val result = MsgSvc.sendToAio(chatType, peerId, message, fromId = fromId)
if (result.first <= 0) { if (result.isFailure) {
return logic(result.exceptionOrNull()?.message ?: "", echo)
}
val pair = result.getOrNull() ?: Pair(0L, 0)
if (pair.first <= 0) {
return logic("send message failed", echo = echo) return logic("send message failed", echo = echo)
} }
return ok(MessageResult( return ok(MessageResult(
msgId = result.second, msgId = pair.second,
time = (result.first * 0.001).toLong() time = (pair.first * 0.001).toLong()
), echo) ), echo)
} }