Skip to content

Commit

Permalink
[core] impl outgoing message sender for friend file message
Browse files Browse the repository at this point in the history
  • Loading branch information
StageGuard committed Sep 1, 2023
1 parent ecee497 commit 02c7086
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 41 deletions.
13 changes: 6 additions & 7 deletions mirai-core/src/commonMain/kotlin/contact/FriendImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ internal class FriendImpl(
val fileUuid = when (appUpResp) {
is OfflineFilleHandleSvr.ApplyUploadV3.Response.FileExists -> appUpResp.fileUuid
is OfflineFilleHandleSvr.ApplyUploadV3.Response.RequireUpload -> appUpResp.fileUuid
else -> error("unreachable!")
else -> assertUnreachable()
}
val file = AbsoluteFriendFileImpl(
this,
Expand Down Expand Up @@ -168,10 +168,9 @@ internal class FriendImpl(
clientVer = "d92615c5",
unknown = 4,
),
fileNameInfo = ExcitingFileNameInfo(filename)
fileNameInfo = ExcitingFileNameInfo(filename = filename)
),
u3 = 0,
u200 = null
u200 = 1
)

Highway.uploadResourceBdh(
Expand All @@ -180,7 +179,6 @@ internal class FriendImpl(
kind = ResourceKind.FRIEND_FILE,
commandId = 69,
extendInfo = ext.toByteArray(FileUploadExt.serializer()),
dataFlag = 0,
callback = if (callback == null) null else fun(it: Long) {
callback.onProgression(file, content, it)
}
Expand All @@ -194,8 +192,9 @@ internal class FriendImpl(
throw IllegalStateException(upSuccResp.message)
}

sendMessage(AllowSendFileMessage + file.toMessage())
return file.toMessage()
val fileMessage = file.toMessage()
sendMessage(AllowSendFileMessage + fileMessage)
return fileMessage
}

override suspend fun delete() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,7 @@ internal abstract class CommonAbsoluteFolderImpl(
),
),
),
u3 = 0,
u200 = 1
u3 = 0
).toByteArray(FileUploadExt.serializer())

callback?.onBegin(file, content)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ internal class AbsoluteFriendFileImpl(
}

override fun toMessage(): FileMessage {
return FriendFileMessageImpl(id, name, size, false)
return FriendFileMessageImpl(id, name, size, md5, true)
}

override suspend fun refreshed(): AbsoluteFile? {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,6 @@ import net.mamoe.mirai.utils.cast
import net.mamoe.mirai.utils.warning
import kotlin.contracts.contract

internal fun FileMessage.checkIsImpl(): GroupFileMessageImpl {
contract { returns() implies (this@checkIsImpl is GroupFileMessageImpl) }
return this as? GroupFileMessageImpl ?: error("FileMessage must not be implemented manually.")
}

@Serializable
@Suppress("ANNOTATION_ARGUMENT_MUST_BE_CONST") // bug
@SerialName(FileMessage.SERIAL_NAME)
Expand Down Expand Up @@ -93,6 +88,7 @@ internal data class FriendFileMessageImpl(
override val id: String,
override val name: String,
override val size: Long,
val md5: ByteArray,
@Transient val allowSend: Boolean = false,
) : FileMessage {
override val internalId: Int
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ package net.mamoe.mirai.internal.message.protocol.impl
import io.ktor.utils.io.core.*
import kotlinx.coroutines.async
import kotlinx.coroutines.coroutineScope
import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.internal.contact.SendMessageStep
import net.mamoe.mirai.internal.contact.impl
import net.mamoe.mirai.internal.contact.uin
import net.mamoe.mirai.internal.message.data.FriendFileMessageImpl
import net.mamoe.mirai.internal.message.data.GroupFileMessageImpl
import net.mamoe.mirai.internal.message.data.checkIsImpl
import net.mamoe.mirai.internal.message.flags.AllowSendFileMessage
import net.mamoe.mirai.internal.message.protocol.MessageProtocol
import net.mamoe.mirai.internal.message.protocol.ProcessorCollector
Expand All @@ -29,20 +31,32 @@ import net.mamoe.mirai.internal.message.protocol.outgoing.OutgoingMessagePipelin
import net.mamoe.mirai.internal.message.protocol.outgoing.OutgoingMessageSender
import net.mamoe.mirai.internal.message.protocol.outgoing.OutgoingMessageTransformer
import net.mamoe.mirai.internal.message.protocol.serialization.MessageSerializer
import net.mamoe.mirai.internal.message.source.OnlineMessageSourceToFriendImpl
import net.mamoe.mirai.internal.message.source.createMessageReceipt
import net.mamoe.mirai.internal.message.visitor.MessageVisitorEx
import net.mamoe.mirai.internal.network.components.ClockHolder.Companion.clock
import net.mamoe.mirai.internal.network.components.SyncController.Companion.syncCookie
import net.mamoe.mirai.internal.network.protocol.data.proto.*
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgSvc
import net.mamoe.mirai.internal.network.protocol.data.proto.ObjMsg
import net.mamoe.mirai.internal.network.protocol.data.proto.SubMsgType0x4
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.internal.network.protocol.packet.chat.FileManagement
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbSendMsg
import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
import net.mamoe.mirai.message.data.FileMessage
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageContent
import net.mamoe.mirai.message.data.SingleMessage
import net.mamoe.mirai.message.data.visitor.RecursiveMessageVisitor
import net.mamoe.mirai.message.data.visitor.acceptChildren
import net.mamoe.mirai.utils.cast
import net.mamoe.mirai.utils.getRandomUnsignedInt
import net.mamoe.mirai.utils.read
import net.mamoe.mirai.utils.systemProp

Expand Down Expand Up @@ -88,8 +102,11 @@ internal class FileMessageProtocol : MessageProtocol() {
override fun visitFileMessage(message: FileMessage, data: Unit) {
if (ALLOW_SENDING_FILE_MESSAGE) return
// #1715
if (message !is GroupFileMessageImpl) error("Customized FileMessage cannot be send")
if (!message.allowSend) {
if (message !is GroupFileMessageImpl && message !is FriendFileMessageImpl) {
error("Customized FileMessage cannot be send")
}
if ((message is GroupFileMessageImpl && !message.allowSend) ||
(message is FriendFileMessageImpl && !message.allowSend)) {
hasFileMessage = true
}
}
Expand All @@ -111,26 +128,91 @@ internal class FileMessageProtocol : MessageProtocol() {
private class FileMessageSender : OutgoingMessageSender {
override suspend fun OutgoingMessagePipelineContext.process() {
val file = currentMessageChain[FileMessage] ?: return
markAsConsumed()

file.checkIsImpl() // TODO: file check impl

val contact = attributes[CONTACT]
val bot = contact.bot

val strategy = components[MessageProtocolStrategy]

val source = coroutineScope {
val source = async {
strategy.constructSourceForSpecialMessage(attributes[ORIGINAL_MESSAGE_AS_CHAIN], 2021)
if (file is FriendFileMessageImpl) {
markAsConsumed()

val msgRand = getRandomUnsignedInt()
val msgSeq = bot.client.sendFriendMessageSeq.next()

val msgSvcPbSendMsgResp = bot.network.sendAndExpect(
MessageSvcPbSendMsg.buildOutgoingUniPacket(
client = bot.client
) {
writeProtoBuf(
MsgSvc.PbSendMsgReq.serializer(),
MsgSvc.PbSendMsgReq(
routingHead = MsgSvc.RoutingHead(
trans0x211 = MsgSvc.Trans0x211(
toUin = contact.uin,
ccCmd = 4
)
),
contentHead = MsgComm.ContentHead(
pkgNum = 1,
pkgIndex = 0,
divSeq = 0
),
msgBody = ImMsgBody.MsgBody(
msgContent = SubMsgType0x4.MsgBody(
msgNotOnlineFile = ImMsgBody.NotOnlineFile(
fileType = 0,
fileUuid = file.id.encodeToByteArray(),
fileMd5 = file.md5,
fileName = file.name.encodeToByteArray(),
fileSize = file.size,
subcmd = 1
)
).toByteArray(SubMsgType0x4.MsgBody.serializer())
),
msgSeq = msgSeq,
msgRand = msgRand,
syncCookie = bot.client.syncCookie ?: byteArrayOf()
)
)
}
)

if (msgSvcPbSendMsgResp is MessageSvcPbSendMsg.Response.SUCCESS) {
val source = OnlineMessageSourceToFriendImpl(
internalIds = intArrayOf(msgRand),
sender = bot,
target = contact.cast(),
time = bot.clock.server.currentTimeSeconds().toInt(),
sequenceIds = intArrayOf(msgSeq),
originalMessage = currentMessageChain,
)

collect(source.createMessageReceipt(contact, false))
return
} else {
error("Failed to send FileMessage to contact $contact: MessageSvcPbSendMsg failed. $msgSvcPbSendMsgResp")
}
}

if (file is GroupFileMessageImpl) {
markAsConsumed()

bot.network.sendAndExpect(FileManagement.Feed(bot.client, contact.id, file.busId, file.id))
val source = coroutineScope {
val source = async {
strategy.constructSourceForSpecialMessage(attributes[ORIGINAL_MESSAGE_AS_CHAIN], 2021)
}

bot.network.sendAndExpect(FileManagement.Feed(bot.client, contact.id, file.busId, file.id))

source.await()
source.await()
}

collect(source.createMessageReceipt(contact, true))
return
}

collect(source.createMessageReceipt(contact, true))
error("FileMessage must not be implemented manually.")
}
}

Expand Down Expand Up @@ -183,7 +265,8 @@ internal class FileMessageProtocol : MessageProtocol() {
FriendFileMessageImpl(
sub0x4.msgNotOnlineFile.fileUuid.decodeToString(),
sub0x4.msgNotOnlineFile.fileName.decodeToString(),
sub0x4.msgNotOnlineFile.fileSize
sub0x4.msgNotOnlineFile.fileSize,
sub0x4.msgNotOnlineFile.fileMd5
)
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ import kotlin.jvm.JvmField

@Serializable
internal class FileUploadExt(
@JvmField @ProtoNumber(1) val u1: Int,
@JvmField @ProtoNumber(2) val u2: Int,
@JvmField @ProtoNumber(3) val u3: Int,
@JvmField @ProtoNumber(1) val u1: Int? = null,
@JvmField @ProtoNumber(2) val u2: Int? = null,
@JvmField @ProtoNumber(3) val u3: Int? = null,
@JvmField @ProtoNumber(100) val entry: FileUploadEntry,
@JvmField @ProtoNumber(200) val u200: Int? = null,
) : ProtoBuf
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ internal class OfflineFilleHandleSvr {
internal object UploadSucc : OutgoingPacketFactory<FileInfo>(
"OfflineFilleHandleSvr.pb_ftn_CMD_REQ_UPLOAD_SUCC-800"
) {


override suspend fun ByteReadPacket.decode(bot: QQAndroidBot): FileInfo {
val resp = readProtoBuf(Cmd0x346.RspBody.serializer())

Expand All @@ -58,7 +56,7 @@ internal class OfflineFilleHandleSvr {
fileInfo.uuid,
fileInfo.fileName,
fileInfo._3sha,
fileInfo.md5,
fileInfo._10mMd5,
fileInfo.fileSize,
fileInfo.expireTime.toLong(),
fileInfo.ownerUin,
Expand All @@ -69,12 +67,14 @@ internal class OfflineFilleHandleSvr {
client: QQAndroidClient,
contact: Contact,
fileUuid: ByteArray,
) = buildOutgoingUniPacket(client) { seq ->
) = buildOutgoingUniPacket(client, sequenceId = 7) { seq ->
writeProtoBuf(
Cmd0x346.ReqBody.serializer(),
Cmd0x346.ReqBody(
cmd = 800,
seq = seq,
businessId = 3,
clientType = 104,
msgUploadSuccReq = Cmd0x346.UploadSuccReq(
senderUin = client.uin,
recverUin = contact.uin,
Expand Down Expand Up @@ -219,12 +219,14 @@ internal class OfflineFilleHandleSvr {
fileSize: Long,
fileMd5: ByteArray,
fileSha1: ByteArray,
) = buildOutgoingUniPacket(client) { seq ->
) = buildOutgoingUniPacket(client, sequenceId = client.sendFriendMessageSeq.next()) { seq ->
writeProtoBuf(
Cmd0x346.ReqBody.serializer(),
Cmd0x346.ReqBody(
cmd = 1700,
seq = seq,
businessId = 3,
clientType = 104,
msgApplyUploadReqV3 = Cmd0x346.ApplyUploadReqV3(
senderUin = client.uin,
recverUin = contact.uin,
Expand All @@ -233,15 +235,12 @@ internal class OfflineFilleHandleSvr {
_10mMd5 = fileMd5,
sha = fileSha1,
localFilepath = "/storage/emulated/0/Android/data/com.tencent.mobileqq/Tencent/QQfile_recv/$filename",
dangerLevel = 0,
totalSpace = 0,
contenttype = 0,
md5 = fileMd5
)
),
flagSupportMediaplatform = 1,
)
)
}
}


}

0 comments on commit 02c7086

Please sign in to comment.