Commit 5cb93c9f authored by ryoii's avatar ryoii

Support FlashImage

parent fb635c14
package net.mamoe.mirai.qqandroid.message
import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.HummerCommelem
import net.mamoe.mirai.qqandroid.network.protocol.data.proto.ImMsgBody
import net.mamoe.mirai.qqandroid.utils.io.serialization.toByteArray
fun FlashImage(image: Image) = when (image) {
is GroupImage -> GroupFlashImageImpl(image)
is FriendImage -> FriendFlashImageImpl(image)
else -> throw IllegalArgumentException("不支持的图片类型(Please use GroupImage or FriendImage)")
}
fun Image.flash() = FlashImage(this)
internal class GroupFlashImageImpl(
override val image: GroupImage
) : AbstractGroupFlashImage() {
private var stringValue: String? = null
get() {
return field ?: kotlin.run {
field = "[mirai:flash:${image.imageId}]"
field
}
}
override fun toString(): String = stringValue!!
override val length: Int get() = stringValue!!.length
override fun get(index: Int) = stringValue!![index]
override fun subSequence(startIndex: Int, endIndex: Int) = stringValue!!.subSequence(startIndex, endIndex)
override fun compareTo(other: String) = other.compareTo(stringValue!!)
}
internal class FriendFlashImageImpl(
override val image: FriendImage
) : AbstractFriendFlashImage() {
private val stringValue = "flash"
override fun toString() = stringValue
override val length = stringValue.length
override fun get(index: Int) = stringValue.get(index)
override fun subSequence(startIndex: Int, endIndex: Int) = stringValue.subSequence(startIndex, endIndex)
override fun compareTo(other: String) = other.compareTo(stringValue)
}
internal fun GroupFlashImageImpl.toJceData() = ImMsgBody.Elem(
commonElem = ImMsgBody.CommonElem(
serviceType = 3,
businessType = 0,
pbElem = HummerCommelem.MsgElemInfoServtype3(
flashTroopPic = ImMsgBody.CustomFace(
filePath = image.filepath,
md5 = image.md5,
pbReserve = byteArrayOf(0x78, 0x06)
)
).toByteArray(HummerCommelem.MsgElemInfoServtype3.serializer())
)
)
internal fun FriendFlashImageImpl.toJceData() = ImMsgBody.Elem(
commonElem = ImMsgBody.CommonElem(
serviceType = 3,
businessType = 0,
pbElem = HummerCommelem.MsgElemInfoServtype3(
flashC2cPic = ImMsgBody.NotOnlineImage(
filePath = image.filepath,
fileId = image.fileId,
resId = image.resourceId,
picMd5 = image.md5,
oldPicMd5 = false,
pbReserve = byteArrayOf(0x78, 0x06)
)
).toByteArray(HummerCommelem.MsgElemInfoServtype3.serializer())
)
)
\ No newline at end of file
...@@ -34,6 +34,7 @@ import net.mamoe.mirai.utils.debug ...@@ -34,6 +34,7 @@ import net.mamoe.mirai.utils.debug
private val UNSUPPORTED_MERGED_MESSAGE_PLAIN = PlainText("你的QQ暂不支持查看[转发多条消息],请期待后续版本。") private val UNSUPPORTED_MERGED_MESSAGE_PLAIN = PlainText("你的QQ暂不支持查看[转发多条消息],请期待后续版本。")
private val UNSUPPORTED_POKE_MESSAGE_PLAIN = PlainText("[戳一戳]请使用最新版手机QQ体验新功能。") private val UNSUPPORTED_POKE_MESSAGE_PLAIN = PlainText("[戳一戳]请使用最新版手机QQ体验新功能。")
private val UNSUPPORTED_FLASH_MESSAGE_PLAIN = PlainText("[闪照]请使用新版手机QQ查看闪照。")
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class) @OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: Boolean): MutableList<ImMsgBody.Elem> { internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: Boolean): MutableList<ImMsgBody.Elem> {
...@@ -115,6 +116,8 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B ...@@ -115,6 +116,8 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B
is OnlineGroupImageImpl -> elements.add(ImMsgBody.Elem(customFace = it.delegate)) is OnlineGroupImageImpl -> elements.add(ImMsgBody.Elem(customFace = it.delegate))
is OnlineFriendImageImpl -> elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate)) is OnlineFriendImageImpl -> elements.add(ImMsgBody.Elem(notOnlineImage = it.delegate))
is OfflineFriendImage -> elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData())) is OfflineFriendImage -> elements.add(ImMsgBody.Elem(notOnlineImage = it.toJceData()))
is GroupFlashImageImpl -> elements.add(it.toJceData()).also { transformOneMessage(UNSUPPORTED_FLASH_MESSAGE_PLAIN) }
is FriendFlashImageImpl -> elements.add(it.toJceData()).also { transformOneMessage(UNSUPPORTED_FLASH_MESSAGE_PLAIN) }
is AtAll -> elements.add(atAllData) is AtAll -> elements.add(atAllData)
is Face -> elements.add(ImMsgBody.Elem(face = it.toJceData())) is Face -> elements.add(ImMsgBody.Elem(face = it.toJceData()))
is QuoteReplyToSend -> { is QuoteReplyToSend -> {
...@@ -156,6 +159,9 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B ...@@ -156,6 +159,9 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B
// 08 09 78 00 A0 01 81 DC 01 C8 01 00 F0 01 00 F8 01 00 90 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 // 08 09 78 00 A0 01 81 DC 01 C8 01 00 F0 01 00 F8 01 00 90 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
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_RICH_MESSAGE))) elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_RICH_MESSAGE)))
} }
this.any<FlashImage>() -> {
elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_DOUTU)))
}
else -> elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_ELSE))) else -> elements.add(ImMsgBody.Elem(generalFlags = ImMsgBody.GeneralFlags(pbReserve = PB_RESERVE_FOR_ELSE)))
} }
} }
...@@ -165,6 +171,7 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B ...@@ -165,6 +171,7 @@ internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: B
private val PB_RESERVE_FOR_RICH_MESSAGE = 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() "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_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() private val PB_RESERVE_FOR_ELSE = "78 00 F8 01 00 C8 02 00".hexToBytes()
@OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class) @OptIn(ExperimentalUnsignedTypes::class, MiraiInternalAPI::class)
...@@ -193,6 +200,13 @@ private fun MessageChain.cleanupRubbishMessageElements(): MessageChain { ...@@ -193,6 +200,13 @@ private fun MessageChain.cleanupRubbishMessageElements(): MessageChain {
var last: SingleMessage? = null var last: SingleMessage? = null
return buildMessageChain(initialSize = this.count()) { return buildMessageChain(initialSize = this.count()) {
this@cleanupRubbishMessageElements.forEach { element -> this@cleanupRubbishMessageElements.forEach { element ->
println(element::class)
last?.apply { println(this::class) }
println(element is PlainText)
println(last is FlashImage)
println(element == UNSUPPORTED_FLASH_MESSAGE_PLAIN)
if (last is LongMessage && element is PlainText) { if (last is LongMessage && element is PlainText) {
if (element == UNSUPPORTED_MERGED_MESSAGE_PLAIN) { if (element == UNSUPPORTED_MERGED_MESSAGE_PLAIN) {
last = element last = element
...@@ -205,6 +219,12 @@ private fun MessageChain.cleanupRubbishMessageElements(): MessageChain { ...@@ -205,6 +219,12 @@ private fun MessageChain.cleanupRubbishMessageElements(): MessageChain {
return@forEach return@forEach
} }
} }
if (last is FlashImage && element is PlainText) {
if (element == UNSUPPORTED_FLASH_MESSAGE_PLAIN) {
last = element
return@forEach
}
}
add(element) add(element)
last = element last = element
...@@ -280,6 +300,15 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(message: MessageChainBuilde ...@@ -280,6 +300,15 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(message: MessageChainBuilde
val proto = it.commonElem.pbElem.loadAs(HummerCommelem.MsgElemInfoServtype2.serializer()) val proto = it.commonElem.pbElem.loadAs(HummerCommelem.MsgElemInfoServtype2.serializer())
message.add(PokeMessage(proto.pokeType, proto.vaspokeId)) message.add(PokeMessage(proto.pokeType, proto.vaspokeId))
} }
3 -> {
val proto = it.commonElem.pbElem.loadAs(HummerCommelem.MsgElemInfoServtype3.serializer())
if (proto.flashTroopPic != null) {
message.add(GroupFlashImageImpl(OnlineGroupImageImpl(proto.flashTroopPic)))
}
if (proto.flashC2cPic != null) {
message.add(FriendFlashImageImpl(OnlineFriendImageImpl(proto.flashC2cPic)))
}
}
} }
} }
else -> { else -> {
......
package net.mamoe.mirai.message.data
sealed class FlashImage : MessageContent {
companion object Key : Message.Key<FlashImage>
abstract val image : Image
}
abstract class AbstractGroupFlashImage : FlashImage() {
abstract override val image: GroupImage
}
abstract class AbstractFriendFlashImage : FlashImage() {
abstract override val image: FriendImage
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment