Support Group VoiceMessage receiving

This commit is contained in:
ryoii 2020-05-02 04:46:51 +08:00
parent 9924d37e54
commit 1dbeb44f5b
4 changed files with 78 additions and 2 deletions

View File

@ -11,6 +11,7 @@
package net.mamoe.mirai.qqandroid.message
import kotlinx.io.core.String
import kotlinx.io.core.discardExact
import kotlinx.io.core.readUInt
import kotlinx.io.core.toByteArray
@ -156,6 +157,7 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B
is VipFace -> {
transformOneMessage(PlainText(it.contentToString()))
}
is PttMessage,
is ForwardMessage,
is MessageSource, // mirai metadata only
is RichMessage // already transformed above
@ -187,6 +189,9 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B
this.anyIsInstance<FlashImage>() -> {
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_DOUTU)))
}
this.anyIsInstance<PttMessage>() -> {
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_PTT)))
}
else -> elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_ELSE)))
}
}
@ -197,6 +202,9 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B
private val PB_RESERVE_FOR_RICH_MESSAGE =
"08 09 78 00 C8 01 00 F0 01 00 F8 01 00 90 02 00 C8 02 00 98 03 00 A0 03 20 B0 03 00 C0 03 00 D0 03 00 E8 03 00 8A 04 02 08 03 90 04 80 80 80 10 B8 04 00 C0 04 00".hexToBytes()
private val PB_RESERVE_FOR_PTT =
"78 00 F8 01 00 C8 02 00 AA 03 26 08 22 12 22 41 20 41 3B 25 3E 16 45 3F 43 2F 29 3E 44 24 14 18 46 3D 2B 4A 44 3A 18 2E 19 29 1B 26 32 31 31 29 43".hexToBytes()
@Suppress("SpellCheckingInspection")
private val PB_RESERVE_FOR_DOUTU = "78 00 90 01 01 F8 01 00 A0 02 00 C8 02 00".hexToBytes()
private val PB_RESERVE_FOR_ELSE = "78 00 F8 01 00 C8 02 00".hexToBytes()
@ -209,8 +217,16 @@ internal fun MsgComm.Msg.toMessageChain(
isTemp: Boolean = false
): MessageChain {
val elements = this.msgBody.richText.elems
val ptt = this.msgBody.richText.ptt
return buildMessageChain(elements.size + 1) {
val pptMsg = ptt?.run {
when(fileType) {
4 -> Voice(String(fileName), fileMd5, String(downPara))
else -> null
}
}
return buildMessageChain(elements.size + 1 + if (pptMsg == null) 0 else 1) {
if (onlineSource) {
when {
isTemp -> +MessageSourceFromTempImpl(bot, this@toMessageChain)
@ -221,6 +237,7 @@ internal fun MsgComm.Msg.toMessageChain(
+OfflineMessageSourceImplByMsg(this@toMessageChain, bot)
}
elements.joinToMessageChain(groupIdOrZero, bot, this)
pptMsg?.let(::add)
}.cleanupRubbishMessageElements()
}

View File

@ -17,6 +17,7 @@ import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.*
import kotlinx.io.core.ByteReadPacket
import kotlinx.io.core.discardExact
import kotlinx.io.core.toByteArray
import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.Friend
import net.mamoe.mirai.contact.Group
@ -32,6 +33,9 @@ import net.mamoe.mirai.getFriendOrNull
import net.mamoe.mirai.message.FriendMessage
import net.mamoe.mirai.message.TempMessage
import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.PttMessage
import net.mamoe.mirai.message.data.Voice
import net.mamoe.mirai.message.data.firstOrNull
import net.mamoe.mirai.qqandroid.QQAndroidBot
import net.mamoe.mirai.qqandroid.contact.GroupImpl
import net.mamoe.mirai.qqandroid.contact.checkIsFriendImpl
@ -51,6 +55,7 @@ import net.mamoe.mirai.qqandroid.network.protocol.packet.*
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.GroupInfoImpl
import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.NewContact
import net.mamoe.mirai.qqandroid.network.protocol.packet.list.FriendList
import net.mamoe.mirai.qqandroid.utils._miraiContentToString
import net.mamoe.mirai.qqandroid.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.qqandroid.utils.io.serialization.readUniPacket
import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
@ -280,6 +285,10 @@ internal class MessageSvc {
} else return@mapNotNull null
}
}
208 -> {
// friend ptt
return@mapNotNull null
}
141 -> {
val tmpHead = msg.msgHead.c2cTmpMsgHead ?: return@mapNotNull null
val member = bot.getGroupByUinOrNull(tmpHead.groupUin)?.getOrNull(msg.msgHead.fromUin)
@ -521,7 +530,10 @@ internal class MessageSvc {
contentHead = MsgComm.ContentHead(pkgNum = 1),
msgBody = ImMsgBody.MsgBody(
richText = ImMsgBody.RichText(
elems = message.toRichTextElems(forGroup = true, withGeneralFlags = true)
elems = message.toRichTextElems(forGroup = true, withGeneralFlags = true),
ptt = message.firstOrNull(PttMessage)?.run {
ImMsgBody.Ptt(fileName = fileName.toByteArray(), fileMd5 = md5)
}
)
),
msgSeq = client.atomicNextMessageSequenceId(),

View File

@ -0,0 +1,45 @@
package net.mamoe.mirai.message.data
/**
* 需要通过上传到服务器的消息如语音文件
*/
abstract class PttMessage : MessageContent {
companion object Key : Message.Key<PttMessage> {
override val typeName: String
get() = "PttMessage"
}
abstract val fileName: String
abstract val md5: ByteArray
}
/**
* 语音消息, 目前只支持接收和转发
*/
class Voice(
override val fileName: String,
override val md5: ByteArray,
private val _url: String
) : PttMessage() {
companion object Key : Message.Key<Voice> {
override val typeName: String
get() = "Voice"
}
val url: String
get() = if (_url.startsWith("http")) _url
else "http://grouptalk.c2c.qq.com$_url"
private var _stringValue: String? = null
get() = field ?: kotlin.run {
field = "[mirai:voice:$fileName]"
field
}
override fun toString(): String = _stringValue!!
override fun contentToString(): String = "[语音]"
}

View File

@ -233,6 +233,8 @@ internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M?
CustomMessage -> firstIsInstanceOrNull()
CustomMessageMetadata -> firstIsInstanceOrNull()
ForwardMessage -> firstIsInstanceOrNull()
PttMessage -> firstIsInstanceOrNull<PttMessage>()
Voice -> firstIsInstanceOrNull<Voice>()
else -> {
this.forEach { message ->
if (message is CustomMessage) {