This commit is contained in:
fuqiuluo 2024-07-25 00:35:56 +08:00
parent f090ef1937
commit cf01a25ea6
4 changed files with 94 additions and 0 deletions

View File

@ -0,0 +1,51 @@
package com.tencent.qqnt.kernel.nativeinterface;
import java.io.Serializable;
public final class Contact implements IKernelModel, Serializable {
int chatType;
String guildId;
String peerUid;
long serialVersionUID;
public Contact() {
this.serialVersionUID = 1L;
this.peerUid = "";
this.guildId = "";
}
public int getChatType() {
return this.chatType;
}
public String getGuildId() {
return this.guildId;
}
public String getPeerUid() {
return this.peerUid;
}
public void setChatType(int i2) {
this.chatType = i2;
}
public void setGuildId(String str) {
this.guildId = str;
}
public void setPeerUid(String str) {
this.peerUid = str;
}
public String toString() {
return "Contact{chatType=" + this.chatType + ",peerUid=" + this.peerUid + ",guildId=" + this.guildId + ",}";
}
public Contact(int i2, String str, String str2) {
this.serialVersionUID = 1L;
this.chatType = i2;
this.peerUid = str;
this.guildId = str2;
}
}

View File

@ -15,6 +15,7 @@ import com.tencent.qqnt.kernel.nativeinterface.VideoElement
import com.tencent.qqnt.kernelpublic.nativeinterface.Contact import com.tencent.qqnt.kernelpublic.nativeinterface.Contact
import kotlinx.atomicfu.atomic import kotlinx.atomicfu.atomic
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.withTimeoutOrNull import kotlinx.coroutines.withTimeoutOrNull
import moe.fuqiuluo.qqinterface.servlet.TicketSvc import moe.fuqiuluo.qqinterface.servlet.TicketSvc
import moe.fuqiuluo.qqinterface.servlet.transfile.data.TryUpPicData import moe.fuqiuluo.qqinterface.servlet.transfile.data.TryUpPicData
@ -45,6 +46,7 @@ import protobuf.oidb.cmd0x11c5.IndexNode
import protobuf.oidb.cmd0x11c5.MultiMediaReqHead import protobuf.oidb.cmd0x11c5.MultiMediaReqHead
import protobuf.oidb.cmd0x11c5.NtV2RichMediaReq import protobuf.oidb.cmd0x11c5.NtV2RichMediaReq
import protobuf.oidb.cmd0x11c5.NtV2RichMediaRsp import protobuf.oidb.cmd0x11c5.NtV2RichMediaRsp
import protobuf.oidb.cmd0x11c5.RKeyInfo
import protobuf.oidb.cmd0x11c5.SceneInfo import protobuf.oidb.cmd0x11c5.SceneInfo
import protobuf.oidb.cmd0x11c5.UploadInfo import protobuf.oidb.cmd0x11c5.UploadInfo
import protobuf.oidb.cmd0x11c5.UploadReq import protobuf.oidb.cmd0x11c5.UploadReq
@ -63,6 +65,8 @@ import kotlin.time.Duration
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
internal object NtV2RichMediaSvc: QQInterfaces() { internal object NtV2RichMediaSvc: QQInterfaces() {
private lateinit var cacheRKeyInfo: DownloadRkeyRsp
private var lastRefreshRKeyTime = 0L
private val requestIdSeq = atomic(2L) private val requestIdSeq = atomic(2L)
fun fetchGroupResUploadTo(): String { fun fetchGroupResUploadTo(): String {
@ -325,6 +329,9 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
} }
suspend fun getTempNtRKey(): Result<DownloadRkeyRsp> { suspend fun getTempNtRKey(): Result<DownloadRkeyRsp> {
if (System.currentTimeMillis() - lastRefreshRKeyTime < 60 * 60_000 && ::cacheRKeyInfo.isInitialized) {
return Result.success(cacheRKeyInfo)
}
runCatching { runCatching {
val req = NtV2RichMediaReq( val req = NtV2RichMediaReq(
head = MultiMediaReqHead( head = MultiMediaReqHead(
@ -350,6 +357,8 @@ internal object NtV2RichMediaSvc: QQInterfaces() {
} }
val trpc = fromServiceMsg.decodeToTrpcOidb() val trpc = fromServiceMsg.decodeToTrpcOidb()
trpc.buffer.decodeProtobuf<NtV2RichMediaRsp>().downloadRkeyRsp?.let { trpc.buffer.decodeProtobuf<NtV2RichMediaRsp>().downloadRkeyRsp?.let {
cacheRKeyInfo = it
lastRefreshRKeyTime = System.currentTimeMillis()
return Result.success(it) return Result.success(it)
} }
}.onFailure { }.onFailure {

View File

@ -11,6 +11,7 @@ import com.tencent.qqnt.kernel.nativeinterface.PicElement
import kotlinx.coroutines.suspendCancellableCoroutine import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getNtPicRKey import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getNtPicRKey
import moe.fuqiuluo.qqinterface.servlet.transfile.NtV2RichMediaSvc.getTempNtRKey
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
@ -231,6 +232,23 @@ internal object RichProtoSvc: QQInterfaces() {
val isNtServer = originalUrl.startsWith("/download") val isNtServer = originalUrl.startsWith("/download")
val domain = if (isNtServer) MULTIMEDIA_DOMAIN else GPRO_PIC val domain = if (isNtServer) MULTIMEDIA_DOMAIN else GPRO_PIC
if (originalUrl.isNotEmpty()) { if (originalUrl.isNotEmpty()) {
// 高于QQ9.0.70可以直接请求获取rkey
val tmpRKey = getTempNtRKey().onFailure {
LogCenter.log("getTempNtRKey: ${it.stackTraceToString()}", Level.WARN)
}
if (tmpRKey.isSuccess) {
val tmpRKeyRsp = tmpRKey.getOrThrow()
val tmpRKeyMap = hashMapOf<UInt, String>()
tmpRKeyRsp.rkeys?.forEach { rKeyInfo ->
tmpRKeyMap[rKeyInfo.type] = rKeyInfo.rkey
}
val rkey = tmpRKeyMap[10u]
if (rkey != null) {
return "https://$MULTIMEDIA_DOMAIN$originalUrl$rkey"
}
}
// 低于QQ9.0.70但是支持nt资源的客户端支持
if (isNtServer && !originalUrl.contains("rkey=")) { if (isNtServer && !originalUrl.contains("rkey=")) {
getNtPicRKey( getNtPicRKey(
fileId = fileId, fileId = fileId,
@ -267,6 +285,21 @@ internal object RichProtoSvc: QQInterfaces() {
val isNtServer = storeId == 1 || originalUrl.startsWith("/download") val isNtServer = storeId == 1 || originalUrl.startsWith("/download")
val domain = if (isNtServer) MULTIMEDIA_DOMAIN else C2C_PIC val domain = if (isNtServer) MULTIMEDIA_DOMAIN else C2C_PIC
if (originalUrl.isNotEmpty()) { if (originalUrl.isNotEmpty()) {
// 高于QQ9.0.70可以直接请求获取rkey
val tmpRKey = getTempNtRKey()
if (tmpRKey.isSuccess) {
val tmpRKeyRsp = tmpRKey.getOrThrow()
val tmpRKeyMap = hashMapOf<UInt, String>()
tmpRKeyRsp.rkeys?.forEach { rKeyInfo ->
tmpRKeyMap[rKeyInfo.type] = rKeyInfo.rkey
}
val rkey = tmpRKeyMap[20u]
if (rkey != null) {
return "https://$MULTIMEDIA_DOMAIN$originalUrl$rkey"
}
}
// 低于QQ9.0.70但是支持nt资源的客户端支持
if (fileId.isNotEmpty()) getNtPicRKey( if (fileId.isNotEmpty()) getNtPicRKey(
fileId = fileId, fileId = fileId,
md5 = md5, md5 = md5,

View File

@ -42,6 +42,7 @@ internal object AioListener : IKernelMsgListener {
try { try {
if (MessageTempHandler.notify(record)) return if (MessageTempHandler.notify(record)) return
if (record.msgSeq < 0) return if (record.msgSeq < 0) return
if (record.chatType == MsgConstant.KCHATTYPETEMPPUBLICACCOUNT) return // 订阅号不处理
val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId) val msgHash = MessageHelper.generateMsgIdHash(record.chatType, record.msgId)