From 661680e60b3d2a1b533db5d6335fd695e8dc6c00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E6=B1=A0?= Date: Fri, 1 Mar 2024 20:29:28 +0800 Subject: [PATCH] =?UTF-8?q?`Shamrock`:=20=E7=BB=95=E8=BF=87=E8=B5=84?= =?UTF-8?q?=E6=BA=90=E4=B8=8A=E4=BC=A0=E6=A3=80=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 白池 --- .../shamrock/ui/app/ShamrockConfig.kt | 12 +++++ .../shamrock/ui/fragment/DashboardFragment.kt | 34 +++++++++++-- .../fuqiuluo/qqinterface/servlet/MsgSvc.kt | 11 +++-- .../servlet/msg/maker/ElemMaker.kt | 2 +- .../servlet/transfile/NtV2RichMediaSvc.kt | 48 +++++++++++-------- .../shamrock/remote/api/TestAction.kt | 7 --- 6 files changed, 77 insertions(+), 37 deletions(-) diff --git a/app/src/main/java/moe/fuqiuluo/shamrock/ui/app/ShamrockConfig.kt b/app/src/main/java/moe/fuqiuluo/shamrock/ui/app/ShamrockConfig.kt index 7e8e71b..f12999b 100644 --- a/app/src/main/java/moe/fuqiuluo/shamrock/ui/app/ShamrockConfig.kt +++ b/app/src/main/java/moe/fuqiuluo/shamrock/ui/app/ShamrockConfig.kt @@ -162,6 +162,17 @@ object ShamrockConfig { pushUpdate(ctx) } + fun getUploadResourceGroup(ctx: Context): String { + val preferences = ctx.getSharedPreferences("config", 0) + return preferences.getString("up_res_group", "100000000")!! + } + + fun setUploadResourceGroup(ctx: Context, v: String) { + val preferences = ctx.getSharedPreferences("config", 0) + preferences.edit().putString("up_res_group", v).apply() + pushUpdate(ctx) + } + fun getHttpPort(ctx: Context): Int { val preferences = ctx.getSharedPreferences("config", 0) return preferences.getInt("port", 5700) @@ -354,6 +365,7 @@ object ShamrockConfig { "disable_auto_sync_setting" to preferences.getBoolean("disable_auto_sync_setting", false), "forbid_useless_process" to preferences.getBoolean("forbid_useless_process", false), "enable_old_bdh" to preferences.getBoolean("enable_old_bdh", false), + "up_res_group" to preferences.getString("up_res_group", ""), ) } diff --git a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/DashboardFragment.kt b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/DashboardFragment.kt index 30f3bc4..9d195c2 100644 --- a/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/DashboardFragment.kt +++ b/app/src/main/java/moe/fuqiuluo/shamrock/ui/fragment/DashboardFragment.kt @@ -356,6 +356,36 @@ private fun FunctionCard( return@Function true } + run { + val uploadResourceGroup = remember { mutableStateOf(ShamrockConfig.getUploadResourceGroup(ctx)) } + Column( + modifier = Modifier + .absolutePadding(left = 8.dp, right = 8.dp, top = 12.dp, bottom = 0.dp) + ) { + Text( + modifier = Modifier.padding(2.dp), + text = "用来上传资源的群聊,错误的资源上传终点可能导致封禁,请自建一个群聊并填写在下方。", + color = Color.Red, + fontSize = 11.sp + ) + } + TextItem( + title = "接受资源群聊", + desc = "用来上传资源的群聊,请自建一个群聊并填写在下方。", + text = uploadResourceGroup, + hint = "请输入群号", + error = "群号不合法", + checker = { + it.isNotBlank() && it.toULongOrNull() != null + }, + confirm = { + val groupId = uploadResourceGroup.value + ShamrockConfig.setUploadResourceGroup(ctx, groupId) + AppRuntime.log("设置接受资源群聊为[$groupId]。") + } + ) + } + /* Function( title = "专业级接口", @@ -445,9 +475,7 @@ private fun InfoItem( .fillMaxWidth() .combinedClickable(onDoubleClick = { doubleClick?.invoke(content) - }) { - true - } + }) { true } , verticalAlignment = Alignment.CenterVertically ) { 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 3a1ad07..98cbaf4 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/MsgSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/MsgSvc.kt @@ -338,13 +338,13 @@ internal object MsgSvc : BaseSvc() { else -> MessageHelper.decodeCQCode(data["content"].asString) }.onEach { element -> val elementData = element.asJsonObject["data"].asJsonObject - if (element.asJsonObject["type"].asString == "forward") + if (element.asJsonObject["type"].asString == "forward") { forwardMsg[elementData["filename"].asString] = elementData["id"].asString + } } - ).getOrElse { throw Exception("消息合成失败: $it") }.let { - desc[++i] = - (data["name"].asStringOrNull ?: data["uin"].asStringOrNull + ).getOrElse { error("消息合成失败: $it") }.let { + desc[++i] = (data["name"].asStringOrNull ?: data["uin"].asStringOrNull ?: TicketSvc.getNickname()) + ": " + it.first it.second } @@ -353,8 +353,9 @@ internal object MsgSvc : BaseSvc() { } else { error("消息节点缺少id或content字段") } + }.onFailure { + LogCenter.log("消息节点解析失败:${it.stackTraceToString()}", Level.WARN) }.getOrElse { - LogCenter.log("消息节点解析失败:$it", Level.WARN) null } }.ifEmpty { return Result.failure(Exception("消息节点为空")) } diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/msg/maker/ElemMaker.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/msg/maker/ElemMaker.kt index 32cd276..ac7c830 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/msg/maker/ElemMaker.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/msg/maker/ElemMaker.kt @@ -261,7 +261,7 @@ internal class ElemMaker { resources = arrayListOf(file), timeout = 30.seconds ).getOrThrow().first() - LogCenter.log(uploadRet.toString(), Level.DEBUG) + LogCenter.log({ uploadRet.toString() }, Level.DEBUG) val elem = when (chatType) { MsgConstant.KCHATTYPEGROUP -> Elem( diff --git a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/transfile/NtV2RichMediaSvc.kt b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/transfile/NtV2RichMediaSvc.kt index 0a2c8ea..84b5486 100644 --- a/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/transfile/NtV2RichMediaSvc.kt +++ b/xposed/src/main/java/moe/fuqiuluo/qqinterface/servlet/transfile/NtV2RichMediaSvc.kt @@ -1,14 +1,11 @@ package moe.fuqiuluo.qqinterface.servlet.transfile -import android.graphics.Bitmap import android.graphics.BitmapFactory -import android.media.MediaMetadataRetriever import androidx.exifinterface.media.ExifInterface import com.tencent.mobileqq.qroute.QRoute import com.tencent.qqnt.aio.adapter.api.IAIOPttApi import com.tencent.qqnt.kernel.nativeinterface.CommonFileInfo import com.tencent.qqnt.kernel.nativeinterface.Contact -import com.tencent.qqnt.kernel.nativeinterface.FileElement import com.tencent.qqnt.kernel.nativeinterface.MsgConstant import com.tencent.qqnt.kernel.nativeinterface.MsgElement import com.tencent.qqnt.kernel.nativeinterface.PicElement @@ -16,28 +13,19 @@ import com.tencent.qqnt.kernel.nativeinterface.PttElement import com.tencent.qqnt.kernel.nativeinterface.QQNTWrapperUtil import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo import com.tencent.qqnt.kernel.nativeinterface.VideoElement -import com.tencent.qqnt.msg.api.IMsgUtilApi import kotlinx.atomicfu.atomic -import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.suspendCancellableCoroutine -import kotlinx.coroutines.withContext import kotlinx.coroutines.withTimeoutOrNull import moe.fuqiuluo.qqinterface.servlet.BaseSvc import moe.fuqiuluo.qqinterface.servlet.TicketSvc -import moe.fuqiuluo.qqinterface.servlet.transfile.data.Private -import moe.fuqiuluo.qqinterface.servlet.transfile.data.Troop import moe.fuqiuluo.qqinterface.servlet.transfile.data.TryUpPicData -import moe.fuqiuluo.qqinterface.servlet.transfile.data.VideoResource -import moe.fuqiuluo.shamrock.helper.Level import moe.fuqiuluo.shamrock.helper.LogCenter import moe.fuqiuluo.shamrock.helper.MessageHelper -import moe.fuqiuluo.shamrock.helper.TransfileHelper import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig import moe.fuqiuluo.shamrock.tools.hex2ByteArray import moe.fuqiuluo.shamrock.tools.slice import moe.fuqiuluo.shamrock.utils.AudioUtils import moe.fuqiuluo.shamrock.utils.FileUtils -import moe.fuqiuluo.shamrock.utils.MD5 import moe.fuqiuluo.shamrock.utils.MediaType import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher import moe.fuqiuluo.shamrock.xposed.helper.msgService @@ -63,7 +51,6 @@ import protobuf.oidb.cmd0x388.Cmd0x388ReqBody import protobuf.oidb.cmd0x388.Cmd0x388RspBody import protobuf.oidb.cmd0x388.TryUpImgReq import java.io.File -import java.io.FileOutputStream import kotlin.coroutines.resume import kotlin.math.roundToInt import kotlin.random.Random @@ -72,14 +59,30 @@ import kotlin.random.nextULong import kotlin.time.Duration internal object NtV2RichMediaSvc: BaseSvc() { - private const val GROUP_PIC_UPLOAD_TO = "100000000" - private val requestIdSeq = atomic(2L) + private fun fetchGroupResUploadTo(): String { + return ShamrockConfig.getUpResGroup().ifEmpty { "100000000" } + } + + suspend fun tryUploadResourceByNt( + chatType: Int, + elementType: Int, + resources: ArrayList, + timeout: Duration, + retryCnt: Int = 5 + ): Result> { + return internalTryUploadResourceByNt(chatType, elementType, resources, timeout).onFailure { + if (retryCnt > 0) { + return tryUploadResourceByNt(chatType, elementType, resources, timeout, retryCnt - 1) + } + } + } + /** * 批量上传图片 */ - suspend fun tryUploadResourceByNt( + private suspend fun internalTryUploadResourceByNt( chatType: Int, elementType: Int, resources: ArrayList, @@ -276,8 +279,9 @@ internal object NtV2RichMediaSvc: BaseSvc() { } val contact = when(chatType) { MsgConstant.KCHATTYPEC2C -> MessageHelper.generateContact(chatType, TicketSvc.getUin()) - else -> Contact(chatType, GROUP_PIC_UPLOAD_TO, GROUP_PIC_UPLOAD_TO) + else -> Contact(chatType, fetchGroupResUploadTo(), null) } + LogCenter.log(contact.toString()) val result = mutableListOf() withTimeoutOrNull(timeout) { suspendCancellableCoroutine { @@ -297,10 +301,12 @@ internal object NtV2RichMediaSvc: BaseSvc() { message = ArrayList(messages), uniseq = uniseq.qqMsgId ) { _, _ -> - val kernelService = NTServiceFetcher.kernelService - val sessionService = kernelService.wrapperSession - val msgService = sessionService.msgService - msgService.deleteMsg(contact, arrayListOf(uniseq.qqMsgId), null) + if (contact.chatType == MsgConstant.KCHATTYPEGROUP && contact.peerUid == "100000000") { + val kernelService = NTServiceFetcher.kernelService + val sessionService = kernelService.wrapperSession + val msgService = sessionService.msgService + msgService.deleteMsg(contact, arrayListOf(uniseq.qqMsgId), null) + } } it.invokeOnCancellation { RichMediaUploadHandler.removeListener(uniseq.qqMsgId) diff --git a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/TestAction.kt b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/TestAction.kt index 32b8de4..68334d1 100644 --- a/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/TestAction.kt +++ b/xposed/src/main/java/moe/fuqiuluo/shamrock/remote/api/TestAction.kt @@ -24,13 +24,6 @@ fun Routing.testAction() { return } - getOrPost("/send_msg_by_resid") { - val resId = fetchOrThrow("res_id") - val peerId = fetchOrThrow("peer_Id") - val messageType = fetchOrThrow("message_type") - call.respondText(SendMsgByResid(peerId, resId, messageType)) - } - getOrPost("/createUidFromTinyId") { val selfId = fetchOrThrow("selfId").toLong() val peerId = fetchOrThrow("peerId")