mirror of
https://github.com/whitechi73/OpenShamrock.git
synced 2024-08-14 13:12:17 +08:00
Shamrock
: 绕过资源上传检测
Signed-off-by: 白池 <whitechi73@outlook.com>
This commit is contained in:
parent
54b7eb95a8
commit
661680e60b
@ -162,6 +162,17 @@ object ShamrockConfig {
|
|||||||
pushUpdate(ctx)
|
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 {
|
fun getHttpPort(ctx: Context): Int {
|
||||||
val preferences = ctx.getSharedPreferences("config", 0)
|
val preferences = ctx.getSharedPreferences("config", 0)
|
||||||
return preferences.getInt("port", 5700)
|
return preferences.getInt("port", 5700)
|
||||||
@ -354,6 +365,7 @@ object ShamrockConfig {
|
|||||||
"disable_auto_sync_setting" to preferences.getBoolean("disable_auto_sync_setting", false),
|
"disable_auto_sync_setting" to preferences.getBoolean("disable_auto_sync_setting", false),
|
||||||
"forbid_useless_process" to preferences.getBoolean("forbid_useless_process", false),
|
"forbid_useless_process" to preferences.getBoolean("forbid_useless_process", false),
|
||||||
"enable_old_bdh" to preferences.getBoolean("enable_old_bdh", false),
|
"enable_old_bdh" to preferences.getBoolean("enable_old_bdh", false),
|
||||||
|
"up_res_group" to preferences.getString("up_res_group", ""),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -356,6 +356,36 @@ private fun FunctionCard(
|
|||||||
return@Function true
|
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(
|
Function(
|
||||||
title = "专业级接口",
|
title = "专业级接口",
|
||||||
@ -445,9 +475,7 @@ private fun InfoItem(
|
|||||||
.fillMaxWidth()
|
.fillMaxWidth()
|
||||||
.combinedClickable(onDoubleClick = {
|
.combinedClickable(onDoubleClick = {
|
||||||
doubleClick?.invoke(content)
|
doubleClick?.invoke(content)
|
||||||
}) {
|
}) { true }
|
||||||
true
|
|
||||||
}
|
|
||||||
,
|
,
|
||||||
verticalAlignment = Alignment.CenterVertically
|
verticalAlignment = Alignment.CenterVertically
|
||||||
) {
|
) {
|
||||||
|
@ -338,13 +338,13 @@ internal object MsgSvc : BaseSvc() {
|
|||||||
else -> MessageHelper.decodeCQCode(data["content"].asString)
|
else -> MessageHelper.decodeCQCode(data["content"].asString)
|
||||||
}.onEach { element ->
|
}.onEach { element ->
|
||||||
val elementData = element.asJsonObject["data"].asJsonObject
|
val elementData = element.asJsonObject["data"].asJsonObject
|
||||||
if (element.asJsonObject["type"].asString == "forward")
|
if (element.asJsonObject["type"].asString == "forward") {
|
||||||
forwardMsg[elementData["filename"].asString] =
|
forwardMsg[elementData["filename"].asString] =
|
||||||
elementData["id"].asString
|
elementData["id"].asString
|
||||||
|
}
|
||||||
}
|
}
|
||||||
).getOrElse { throw Exception("消息合成失败: $it") }.let {
|
).getOrElse { error("消息合成失败: $it") }.let {
|
||||||
desc[++i] =
|
desc[++i] = (data["name"].asStringOrNull ?: data["uin"].asStringOrNull
|
||||||
(data["name"].asStringOrNull ?: data["uin"].asStringOrNull
|
|
||||||
?: TicketSvc.getNickname()) + ": " + it.first
|
?: TicketSvc.getNickname()) + ": " + it.first
|
||||||
it.second
|
it.second
|
||||||
}
|
}
|
||||||
@ -353,8 +353,9 @@ internal object MsgSvc : BaseSvc() {
|
|||||||
} else {
|
} else {
|
||||||
error("消息节点缺少id或content字段")
|
error("消息节点缺少id或content字段")
|
||||||
}
|
}
|
||||||
|
}.onFailure {
|
||||||
|
LogCenter.log("消息节点解析失败:${it.stackTraceToString()}", Level.WARN)
|
||||||
}.getOrElse {
|
}.getOrElse {
|
||||||
LogCenter.log("消息节点解析失败:$it", Level.WARN)
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}.ifEmpty { return Result.failure(Exception("消息节点为空")) }
|
}.ifEmpty { return Result.failure(Exception("消息节点为空")) }
|
||||||
|
@ -261,7 +261,7 @@ internal class ElemMaker {
|
|||||||
resources = arrayListOf(file),
|
resources = arrayListOf(file),
|
||||||
timeout = 30.seconds
|
timeout = 30.seconds
|
||||||
).getOrThrow().first()
|
).getOrThrow().first()
|
||||||
LogCenter.log(uploadRet.toString(), Level.DEBUG)
|
LogCenter.log({ uploadRet.toString() }, Level.DEBUG)
|
||||||
|
|
||||||
val elem = when (chatType) {
|
val elem = when (chatType) {
|
||||||
MsgConstant.KCHATTYPEGROUP -> Elem(
|
MsgConstant.KCHATTYPEGROUP -> Elem(
|
||||||
|
@ -1,14 +1,11 @@
|
|||||||
package moe.fuqiuluo.qqinterface.servlet.transfile
|
package moe.fuqiuluo.qqinterface.servlet.transfile
|
||||||
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.BitmapFactory
|
import android.graphics.BitmapFactory
|
||||||
import android.media.MediaMetadataRetriever
|
|
||||||
import androidx.exifinterface.media.ExifInterface
|
import androidx.exifinterface.media.ExifInterface
|
||||||
import com.tencent.mobileqq.qroute.QRoute
|
import com.tencent.mobileqq.qroute.QRoute
|
||||||
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
import com.tencent.qqnt.aio.adapter.api.IAIOPttApi
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.CommonFileInfo
|
import com.tencent.qqnt.kernel.nativeinterface.CommonFileInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.Contact
|
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.MsgConstant
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.PicElement
|
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.QQNTWrapperUtil
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo
|
import com.tencent.qqnt.kernel.nativeinterface.RichMediaFilePathInfo
|
||||||
import com.tencent.qqnt.kernel.nativeinterface.VideoElement
|
import com.tencent.qqnt.kernel.nativeinterface.VideoElement
|
||||||
import com.tencent.qqnt.msg.api.IMsgUtilApi
|
|
||||||
import kotlinx.atomicfu.atomic
|
import kotlinx.atomicfu.atomic
|
||||||
import kotlinx.coroutines.Dispatchers
|
|
||||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||||
import kotlinx.coroutines.withContext
|
|
||||||
import kotlinx.coroutines.withTimeoutOrNull
|
import kotlinx.coroutines.withTimeoutOrNull
|
||||||
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
import moe.fuqiuluo.qqinterface.servlet.BaseSvc
|
||||||
import moe.fuqiuluo.qqinterface.servlet.TicketSvc
|
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.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.LogCenter
|
||||||
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
import moe.fuqiuluo.shamrock.helper.MessageHelper
|
||||||
import moe.fuqiuluo.shamrock.helper.TransfileHelper
|
|
||||||
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
import moe.fuqiuluo.shamrock.remote.service.config.ShamrockConfig
|
||||||
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
import moe.fuqiuluo.shamrock.tools.hex2ByteArray
|
||||||
import moe.fuqiuluo.shamrock.tools.slice
|
import moe.fuqiuluo.shamrock.tools.slice
|
||||||
import moe.fuqiuluo.shamrock.utils.AudioUtils
|
import moe.fuqiuluo.shamrock.utils.AudioUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.FileUtils
|
import moe.fuqiuluo.shamrock.utils.FileUtils
|
||||||
import moe.fuqiuluo.shamrock.utils.MD5
|
|
||||||
import moe.fuqiuluo.shamrock.utils.MediaType
|
import moe.fuqiuluo.shamrock.utils.MediaType
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
import moe.fuqiuluo.shamrock.xposed.helper.NTServiceFetcher
|
||||||
import moe.fuqiuluo.shamrock.xposed.helper.msgService
|
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.Cmd0x388RspBody
|
||||||
import protobuf.oidb.cmd0x388.TryUpImgReq
|
import protobuf.oidb.cmd0x388.TryUpImgReq
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
|
||||||
import kotlin.coroutines.resume
|
import kotlin.coroutines.resume
|
||||||
import kotlin.math.roundToInt
|
import kotlin.math.roundToInt
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
@ -72,14 +59,30 @@ import kotlin.random.nextULong
|
|||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
|
|
||||||
internal object NtV2RichMediaSvc: BaseSvc() {
|
internal object NtV2RichMediaSvc: BaseSvc() {
|
||||||
private const val GROUP_PIC_UPLOAD_TO = "100000000"
|
|
||||||
|
|
||||||
private val requestIdSeq = atomic(2L)
|
private val requestIdSeq = atomic(2L)
|
||||||
|
|
||||||
|
private fun fetchGroupResUploadTo(): String {
|
||||||
|
return ShamrockConfig.getUpResGroup().ifEmpty { "100000000" }
|
||||||
|
}
|
||||||
|
|
||||||
|
suspend fun tryUploadResourceByNt(
|
||||||
|
chatType: Int,
|
||||||
|
elementType: Int,
|
||||||
|
resources: ArrayList<File>,
|
||||||
|
timeout: Duration,
|
||||||
|
retryCnt: Int = 5
|
||||||
|
): Result<MutableList<CommonFileInfo>> {
|
||||||
|
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,
|
chatType: Int,
|
||||||
elementType: Int,
|
elementType: Int,
|
||||||
resources: ArrayList<File>,
|
resources: ArrayList<File>,
|
||||||
@ -276,8 +279,9 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
|||||||
}
|
}
|
||||||
val contact = when(chatType) {
|
val contact = when(chatType) {
|
||||||
MsgConstant.KCHATTYPEC2C -> MessageHelper.generateContact(chatType, TicketSvc.getUin())
|
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<CommonFileInfo>()
|
val result = mutableListOf<CommonFileInfo>()
|
||||||
withTimeoutOrNull(timeout) {
|
withTimeoutOrNull(timeout) {
|
||||||
suspendCancellableCoroutine {
|
suspendCancellableCoroutine {
|
||||||
@ -297,10 +301,12 @@ internal object NtV2RichMediaSvc: BaseSvc() {
|
|||||||
message = ArrayList(messages),
|
message = ArrayList(messages),
|
||||||
uniseq = uniseq.qqMsgId
|
uniseq = uniseq.qqMsgId
|
||||||
) { _, _ ->
|
) { _, _ ->
|
||||||
val kernelService = NTServiceFetcher.kernelService
|
if (contact.chatType == MsgConstant.KCHATTYPEGROUP && contact.peerUid == "100000000") {
|
||||||
val sessionService = kernelService.wrapperSession
|
val kernelService = NTServiceFetcher.kernelService
|
||||||
val msgService = sessionService.msgService
|
val sessionService = kernelService.wrapperSession
|
||||||
msgService.deleteMsg(contact, arrayListOf(uniseq.qqMsgId), null)
|
val msgService = sessionService.msgService
|
||||||
|
msgService.deleteMsg(contact, arrayListOf(uniseq.qqMsgId), null)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
it.invokeOnCancellation {
|
it.invokeOnCancellation {
|
||||||
RichMediaUploadHandler.removeListener(uniseq.qqMsgId)
|
RichMediaUploadHandler.removeListener(uniseq.qqMsgId)
|
||||||
|
@ -24,13 +24,6 @@ fun Routing.testAction() {
|
|||||||
return
|
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") {
|
getOrPost("/createUidFromTinyId") {
|
||||||
val selfId = fetchOrThrow("selfId").toLong()
|
val selfId = fetchOrThrow("selfId").toLong()
|
||||||
val peerId = fetchOrThrow("peerId")
|
val peerId = fetchOrThrow("peerId")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user