Shamrock: Support télécharger un fichier obtenir un ID de fichier

This commit is contained in:
WhiteChi 2023-11-25 19:55:00 +08:00
parent 1a814e565a
commit 4fedab719b
6 changed files with 105 additions and 29 deletions

View File

@ -327,10 +327,10 @@ internal sealed class MessageElemConverter: IMessageConvert {
val fileSize = fileMsg.fileSize
val expireTime = fileMsg.expireTime ?: 0
val fileId = fileMsg.fileUuid
val bizId = fileMsg.fileBizId
val bizId = fileMsg.fileBizId ?: 0
val fileSubId = fileMsg.fileSubId ?: ""
val url = if (chatType == MsgConstant.KCHATTYPEC2C) RichProtoSvc.getC2CFileDownUrl(fileId, fileSubId)
else RichProtoSvc.getGroupFileDownUrl(peerId.toLong(), fileId, fileMsg.fileBizId)
else RichProtoSvc.getGroupFileDownUrl(peerId.toLong(), fileId, bizId)
return MessageSegment(
type = "file",

View File

@ -5,12 +5,15 @@ import android.graphics.BitmapFactory
import android.media.MediaMetadataRetriever
import com.tencent.mobileqq.qroute.QRoute
import com.tencent.qqnt.kernel.nativeinterface.FileElement
import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
import com.tencent.qqnt.msg.api.IMsgService
import com.tencent.qqnt.msg.api.IMsgUtilApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@ -19,11 +22,13 @@ import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.helper.TransfileHelper
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.remote.service.api.RichMediaUploadHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.shamrock.utils.MD5
import java.io.File
import java.io.FileOutputStream
import kotlin.coroutines.resume
internal object UploadGroupFile : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
@ -94,16 +99,36 @@ internal object UploadGroupFile : IActionHandler() {
msgElement.elementType = MsgConstant.KELEMTYPEFILE
msgElement.fileElement = fileElement
// 根据文件大小调整超时时间
val msgIdPair = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEGROUP)
val info = (withTimeoutOrNull((srcFile.length() / (300 * 1024)) * 1000 + 5000) {
val msgService = QRoute.api(IMsgService::class.java)
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId)
suspendCancellableCoroutine<FileTransNotifyInfo?> {
msgService.sendMsgWithMsgId(
MessageHelper.generateContact(MsgConstant.KCHATTYPEGROUP, groupId), msgIdPair.second, arrayListOf(msgElement)
contact, msgIdPair.second, arrayListOf(msgElement)
) { code, reason ->
LogCenter.log("群文件消息发送异常(code = $code, reason = $reason)")
it.resume(null)
}
RichMediaUploadHandler.registerListener(msgIdPair.second) {
it.resume(this)
return@registerListener true
}
}
} ?: return error("上传文件失败", echo)).also {
if (it.commonFileInfo == null) {
return error(it.fileErrMsg ?: "上传文件失败", echo)
}
}.commonFileInfo
return ok(data = FileUploadResult(
msgHash = msgIdPair.first
msgHash = msgIdPair.first,
bizid = info.bizType ?: 0,
md5 = info.md5,
sha = info.sha,
sha3 = info.sha3,
fileId = info.uuid
), echo = echo)
}
@ -114,5 +139,10 @@ internal object UploadGroupFile : IActionHandler() {
@Serializable
data class FileUploadResult(
@SerialName("msg_id") val msgHash: Int,
@SerialName("bizid") val bizid: Int,
@SerialName("md5") val md5: String,
@SerialName("sha") val sha: String,
@SerialName("sha3") val sha3: String,
@SerialName("file_id") val fileId: String
)
}

View File

@ -5,12 +5,15 @@ import android.graphics.BitmapFactory
import android.media.MediaMetadataRetriever
import com.tencent.mobileqq.qroute.QRoute
import com.tencent.qqnt.kernel.nativeinterface.FileElement
import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
import com.tencent.qqnt.kernel.nativeinterface.MsgConstant
import com.tencent.qqnt.kernel.nativeinterface.MsgElement
import com.tencent.qqnt.msg.api.IMsgService
import com.tencent.qqnt.msg.api.IMsgUtilApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeoutOrNull
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonElement
@ -20,11 +23,13 @@ import moe.fuqiuluo.shamrock.helper.MessageHelper
import moe.fuqiuluo.shamrock.helper.TransfileHelper
import moe.fuqiuluo.shamrock.remote.action.ActionSession
import moe.fuqiuluo.shamrock.remote.action.IActionHandler
import moe.fuqiuluo.shamrock.remote.service.api.RichMediaUploadHandler
import moe.fuqiuluo.shamrock.tools.EmptyJsonString
import moe.fuqiuluo.shamrock.utils.FileUtils
import moe.fuqiuluo.shamrock.utils.MD5
import java.io.File
import java.io.FileOutputStream
import kotlin.coroutines.resume
internal object UploadPrivateFile : IActionHandler() {
override suspend fun internalHandle(session: ActionSession): String {
@ -95,26 +100,40 @@ internal object UploadPrivateFile : IActionHandler() {
msgElement.elementType = MsgConstant.KELEMTYPEFILE
msgElement.fileElement = fileElement
// 根据文件大小调整超时时间
val msgIdPair = MessageHelper.generateMsgId(MsgConstant.KCHATTYPEC2C)
val info = (withTimeoutOrNull((srcFile.length() / (300 * 1024)) * 1000 + 5000) {
val msgService = QRoute.api(IMsgService::class.java)
val contact = MessageHelper.generateContact(MsgConstant.KCHATTYPEC2C, userId)
suspendCancellableCoroutine<FileTransNotifyInfo?> {
msgService.sendMsgWithMsgId(
MessageHelper.generateContact(MsgConstant.KCHATTYPEC2C, userId), msgIdPair.second, arrayListOf(msgElement)
contact, msgIdPair.second, arrayListOf(msgElement)
) { code, reason ->
if (code != 0)
LogCenter.log("私聊文件消息发送异常(code = $code, reason = $reason)")
it.resume(null)
}
RichMediaUploadHandler.registerListener(msgIdPair.second) {
it.resume(this)
return@registerListener true
}
}
} ?: return error("上传文件失败", echo)).also {
if (it.commonFileInfo == null) {
return error(it.fileErrMsg ?: "上传文件失败", echo)
}
}.commonFileInfo
return ok(data = FileUploadResult(
msgHash = msgIdPair.first
return ok(data = UploadGroupFile.FileUploadResult(
msgHash = msgIdPair.first,
bizid = info.bizType ?: 0,
md5 = info.md5,
sha = info.sha,
sha3 = info.sha3,
fileId = info.uuid
), echo = echo)
}
override val requiredParams: Array<String> = arrayOf("user_id", "file", "name")
override fun path(): String = "upload_private_file"
@Serializable
data class FileUploadResult(
@SerialName("msg_id") val msgHash: Int,
)
}

View File

@ -0,0 +1,27 @@
package moe.fuqiuluo.shamrock.remote.service.api
import com.tencent.qqnt.kernel.nativeinterface.FileTransNotifyInfo
internal object RichMediaUploadHandler {
private val listeners by lazy {
mutableMapOf<Long, FileTransNotifyInfo.() -> Boolean>()
}
fun registerListener(key: Long, value: FileTransNotifyInfo.() -> Boolean) {
listeners[key] = value
}
fun removeListener(key: Long) {
listeners.remove(key)
}
fun notify(info: FileTransNotifyInfo): Boolean {
listeners[info.msgId]?.let {
if (it(info)) {
listeners.remove(info.msgId)
return true
}
}
return false
}
}

View File

@ -15,6 +15,7 @@ import moe.fuqiuluo.shamrock.helper.Level
import moe.fuqiuluo.shamrock.helper.LogCenter
import moe.fuqiuluo.shamrock.helper.db.MessageDB
import moe.fuqiuluo.shamrock.remote.service.api.GlobalEventTransmitter
import moe.fuqiuluo.shamrock.remote.service.api.RichMediaUploadHandler
import moe.fuqiuluo.shamrock.remote.service.data.push.MessageTempSource
import moe.fuqiuluo.shamrock.remote.service.data.push.PostType
import mqq.app.MobileQQ
@ -347,6 +348,11 @@ internal object AioListener: IKernelMsgListener {
}
}
override fun onRichMediaUploadComplete(notifyInfo: FileTransNotifyInfo) {
//LogCenter.log("onRichMediaUploadComplete($notifyInfo)", Level.DEBUG)
RichMediaUploadHandler.notify(notifyInfo)
}
override fun onRecvOnlineFileMsg(arrayList: ArrayList<MsgRecord>?) {
LogCenter.log(("onRecvOnlineFileMsg" + arrayList?.joinToString { ", " }), Level.DEBUG)
}
@ -359,10 +365,6 @@ internal object AioListener: IKernelMsgListener {
}
override fun onRichMediaUploadComplete(fileTransNotifyInfo: FileTransNotifyInfo) {
}
override fun onSearchGroupFileInfoUpdate(searchGroupFileResult: SearchGroupFileResult?) {
LogCenter.log("onSearchGroupFileInfoUpdate($searchGroupFileResult)", Level.DEBUG)
}

View File

@ -336,7 +336,6 @@ internal object PrimitiveListener {
val targetUid = pb[1, 3, 2, 3].asUtf8String
val type = pb[1, 3, 2, 4].asInt
val operation = ContactHelper.getUinByUidAsync(pb[1, 3, 2, 5].asUtf8String).toLong()
// 131 passive | 130 active | 3 kick_self
val target = ContactHelper.getUinByUidAsync(targetUid).toLong()
val subtype = when(type) {
@ -344,7 +343,6 @@ internal object PrimitiveListener {
131 -> NoticeSubType.Kick
3 -> NoticeSubType.KickMe
else -> {
NoticeSubType.Kick
}
}