mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-10 12:10:10 +08:00
Fix serialization
This commit is contained in:
parent
5196cc410a
commit
eacdfed97a
@ -12,6 +12,7 @@ package net.mamoe.mirai.message
|
|||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import kotlinx.serialization.modules.PolymorphicModuleBuilder
|
import kotlinx.serialization.modules.PolymorphicModuleBuilder
|
||||||
@ -21,6 +22,7 @@ import kotlinx.serialization.modules.polymorphic
|
|||||||
import net.mamoe.mirai.Mirai
|
import net.mamoe.mirai.Mirai
|
||||||
import net.mamoe.mirai.message.data.*
|
import net.mamoe.mirai.message.data.*
|
||||||
import net.mamoe.mirai.utils.MiraiExperimentalApi
|
import net.mamoe.mirai.utils.MiraiExperimentalApi
|
||||||
|
import net.mamoe.mirai.utils.MiraiInternalApi
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
@MiraiExperimentalApi
|
@MiraiExperimentalApi
|
||||||
@ -34,9 +36,12 @@ public interface MessageSerializer {
|
|||||||
public fun clearRegisteredSerializers()
|
public fun clearRegisteredSerializers()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal object MessageSourceSerializer : KSerializer<MessageSource> {
|
@MiraiInternalApi
|
||||||
|
public open class MessageSourceSerializerImpl(serialName: String) : KSerializer<MessageSource> {
|
||||||
|
public companion object : MessageSourceSerializerImpl("net.mamoe.mirai.message.data.MessageSource")
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class SerialData(
|
internal class SerialData(
|
||||||
val kind: MessageSourceKind,
|
val kind: MessageSourceKind,
|
||||||
val bot: Long,
|
val bot: Long,
|
||||||
val ids: IntArray,
|
val ids: IntArray,
|
||||||
@ -47,7 +52,17 @@ internal object MessageSourceSerializer : KSerializer<MessageSource> {
|
|||||||
val originalMessage: MessageChain,
|
val originalMessage: MessageChain,
|
||||||
)
|
)
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor = SerialData.serializer().descriptor
|
override val descriptor: SerialDescriptor = buildClassSerialDescriptor(serialName) {
|
||||||
|
val desc = SerialData.serializer().descriptor
|
||||||
|
repeat(SerialData.serializer().descriptor.elementsCount) { index ->
|
||||||
|
element(
|
||||||
|
desc.getElementName(index),
|
||||||
|
desc.getElementDescriptor(index),
|
||||||
|
desc.getElementAnnotations(index),
|
||||||
|
desc.isElementOptional(index)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
// buildClassSerialDescriptor("MessageSource") {
|
// buildClassSerialDescriptor("MessageSource") {
|
||||||
// element("bot", Long.serializer().descriptor)
|
// element("bot", Long.serializer().descriptor)
|
||||||
// element("ids", ArraySerializer(Int.serializer()).descriptor)
|
// element("ids", ArraySerializer(Int.serializer()).descriptor)
|
||||||
@ -96,7 +111,6 @@ private val builtInSerializersModule by lazy {
|
|||||||
contextual(CustomMessage::class, CustomMessage.serializer())
|
contextual(CustomMessage::class, CustomMessage.serializer())
|
||||||
contextual(CustomMessageMetadata::class, CustomMessageMetadata.serializer())
|
contextual(CustomMessageMetadata::class, CustomMessageMetadata.serializer())
|
||||||
contextual(Face::class, Face.serializer())
|
contextual(Face::class, Face.serializer())
|
||||||
contextual(MessageSource::class, MessageSource.serializer())
|
|
||||||
contextual(Image::class, Image.Serializer)
|
contextual(Image::class, Image.Serializer)
|
||||||
contextual(PlainText::class, PlainText.serializer())
|
contextual(PlainText::class, PlainText.serializer())
|
||||||
contextual(QuoteReply::class, QuoteReply.serializer())
|
contextual(QuoteReply::class, QuoteReply.serializer())
|
||||||
@ -117,8 +131,12 @@ private val builtInSerializersModule by lazy {
|
|||||||
contextual(FlashImage::class, FlashImage.serializer())
|
contextual(FlashImage::class, FlashImage.serializer())
|
||||||
|
|
||||||
fun PolymorphicModuleBuilder<SingleMessage>.singleMessageSubclasses() {
|
fun PolymorphicModuleBuilder<SingleMessage>.singleMessageSubclasses() {
|
||||||
|
// subclass(MessageSource::class, MessageSource.serializer())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// contextual(MessageSource::class, MessageSource.serializer())
|
||||||
|
polymorphicDefault(MessageSource::class) { MessageSource.serializer() }
|
||||||
|
|
||||||
fun PolymorphicModuleBuilder<MessageMetadata>.messageMetadataSubclasses() {
|
fun PolymorphicModuleBuilder<MessageMetadata>.messageMetadataSubclasses() {
|
||||||
subclass(MessageSource::class, MessageSource.serializer())
|
subclass(MessageSource::class, MessageSource.serializer())
|
||||||
subclass(QuoteReply::class, QuoteReply.serializer())
|
subclass(QuoteReply::class, QuoteReply.serializer())
|
||||||
@ -148,7 +166,14 @@ private val builtInSerializersModule by lazy {
|
|||||||
subclass(FlashImage::class, FlashImage.serializer())
|
subclass(FlashImage::class, FlashImage.serializer())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contextual(Message::class, Message.Serializer)
|
||||||
|
// contextual(SingleMessage::class, SingleMessage.Serializer)
|
||||||
contextual(MessageChain::class, MessageChain.Serializer)
|
contextual(MessageChain::class, MessageChain.Serializer)
|
||||||
|
contextual(MessageChainImpl::class, MessageChainImpl.serializer())
|
||||||
|
|
||||||
|
polymorphic(MessageChain::class) {
|
||||||
|
subclass(MessageChainImpl::class, MessageChainImpl.serializer())
|
||||||
|
}
|
||||||
polymorphicDefault(MessageChain::class) { MessageChainImpl.serializer() }
|
polymorphicDefault(MessageChain::class) { MessageChainImpl.serializer() }
|
||||||
|
|
||||||
polymorphic(AbstractServiceMessage::class) {
|
polymorphic(AbstractServiceMessage::class) {
|
||||||
@ -156,9 +181,15 @@ private val builtInSerializersModule by lazy {
|
|||||||
subclass(ForwardMessageInternal::class, ForwardMessageInternal.serializer())
|
subclass(ForwardMessageInternal::class, ForwardMessageInternal.serializer())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// polymorphic(SingleMessage::class) {
|
||||||
|
// subclass(MessageSource::class, MessageSource.serializer())
|
||||||
|
// default {
|
||||||
|
// Message.Serializer.serializersModule.getPolymorphic(Message::class, it)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
polymorphicDefault(Image::class) { Image.Serializer }
|
polymorphicDefault(Image::class) { Image.Serializer }
|
||||||
|
|
||||||
contextual(Message::class, Message.Serializer)
|
|
||||||
// polymorphic(Message::class) {
|
// polymorphic(Message::class) {
|
||||||
// subclass(PlainText::class, PlainText.serializer())
|
// subclass(PlainText::class, PlainText.serializer())
|
||||||
// }
|
// }
|
||||||
@ -166,6 +197,7 @@ private val builtInSerializersModule by lazy {
|
|||||||
messageContentSubclasses()
|
messageContentSubclasses()
|
||||||
messageMetadataSubclasses()
|
messageMetadataSubclasses()
|
||||||
singleMessageSubclasses()
|
singleMessageSubclasses()
|
||||||
|
subclass(MessageChainImpl::class, MessageChainImpl.serializer())
|
||||||
}
|
}
|
||||||
|
|
||||||
//contextual(SingleMessage::class, SingleMessage.Serializer)
|
//contextual(SingleMessage::class, SingleMessage.Serializer)
|
||||||
|
@ -209,8 +209,12 @@ public interface Message { // must be interface. Don't consider any changes.
|
|||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun deserializeFromJsonString(string: String, json: Json = Json.Default): Message =
|
public fun deserializeFromJsonString(
|
||||||
json.decodeFromString(Serializer, string)
|
string: String,
|
||||||
|
json: Json = Json { serializersModule = Serializer.serializersModule }
|
||||||
|
): Message {
|
||||||
|
return json.decodeFromString(Serializer, string)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 [Message] 序列化为 JSON 字符串.
|
* 将 [Message] 序列化为 JSON 字符串.
|
||||||
@ -218,8 +222,9 @@ public interface Message { // must be interface. Don't consider any changes.
|
|||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
public fun Message.serializeToJsonString(json: Json = Json.Default): String =
|
public fun Message.serializeToJsonString(
|
||||||
json.encodeToString(Serializer, this)
|
json: Json = Json { serializersModule = Serializer.serializersModule }
|
||||||
|
): String = json.encodeToString(Serializer, this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 将 [Message] 序列化为指定格式的字符串.
|
* 将 [Message] 序列化为指定格式的字符串.
|
||||||
@ -320,9 +325,10 @@ public inline operator fun Message.times(count: Int): MessageChain = this.repeat
|
|||||||
/**
|
/**
|
||||||
* 单个消息元素. 与之相对的是 [MessageChain], 是多个 [SingleMessage] 的集合.
|
* 单个消息元素. 与之相对的是 [MessageChain], 是多个 [SingleMessage] 的集合.
|
||||||
*/
|
*/
|
||||||
@Serializable(SingleMessage.Serializer::class)
|
// @Serializable(SingleMessage.Serializer::class)
|
||||||
public interface SingleMessage : Message {
|
public interface SingleMessage : Message {
|
||||||
public object Serializer : KSerializer<SingleMessage> by PolymorphicSerializer(SingleMessage::class)
|
// @kotlinx.serialization.Serializer(forClass = SingleMessage::class)
|
||||||
|
// public object Serializer : KSerializer<SingleMessage> by PolymorphicSerializer(SingleMessage::class)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -13,12 +13,12 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.message.data
|
package net.mamoe.mirai.message.data
|
||||||
|
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.*
|
||||||
import kotlinx.serialization.Serializable
|
|
||||||
import kotlinx.serialization.builtins.ListSerializer
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
import net.mamoe.mirai.event.events.MessageEvent
|
import net.mamoe.mirai.event.events.MessageEvent
|
||||||
import net.mamoe.mirai.message.code.CodableMessage
|
import net.mamoe.mirai.message.code.CodableMessage
|
||||||
import net.mamoe.mirai.message.data.MessageSource.Key.quote
|
import net.mamoe.mirai.message.data.MessageSource.Key.quote
|
||||||
@ -104,6 +104,42 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess, Coda
|
|||||||
override fun appendMiraiCode(builder: StringBuilder) {
|
override fun appendMiraiCode(builder: StringBuilder) {
|
||||||
forEach { it.safeCast<CodableMessage>()?.appendMiraiCode(builder) }
|
forEach { it.safeCast<CodableMessage>()?.appendMiraiCode(builder) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* 从 JSON 字符串解析 [MessageChain]
|
||||||
|
* @see serializeToJsonString
|
||||||
|
*/
|
||||||
|
@JvmOverloads
|
||||||
|
@JvmStatic
|
||||||
|
public fun deserializeFromJsonString(
|
||||||
|
string: String,
|
||||||
|
json: Json = Json { serializersModule = Message.Serializer.serializersModule }
|
||||||
|
): MessageChain {
|
||||||
|
return json.decodeFromString(Serializer, string)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 [MessageChain] 序列化为 JSON 字符串.
|
||||||
|
* @see deserializeFromJsonString
|
||||||
|
*/
|
||||||
|
@JvmOverloads
|
||||||
|
@JvmStatic
|
||||||
|
public fun MessageChain.serializeToJsonString(
|
||||||
|
json: Json = Json { serializersModule = Message.Serializer.serializersModule }
|
||||||
|
): String = json.encodeToString(Message.Serializer, this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 [MessageChain] 序列化为指定格式的字符串.
|
||||||
|
*
|
||||||
|
* @see serializeToJsonString
|
||||||
|
* @see StringFormat.encodeToString
|
||||||
|
*/
|
||||||
|
@ExperimentalSerializationApi
|
||||||
|
@JvmStatic
|
||||||
|
public fun MessageChain.serializeToString(format: StringFormat): String =
|
||||||
|
format.encodeToString(Serializer, this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// region accessors
|
// region accessors
|
||||||
|
@ -25,7 +25,7 @@ import net.mamoe.mirai.contact.*
|
|||||||
import net.mamoe.mirai.event.events.MessageEvent
|
import net.mamoe.mirai.event.events.MessageEvent
|
||||||
import net.mamoe.mirai.message.MessageReceipt
|
import net.mamoe.mirai.message.MessageReceipt
|
||||||
import net.mamoe.mirai.message.MessageReceipt.Companion.recall
|
import net.mamoe.mirai.message.MessageReceipt.Companion.recall
|
||||||
import net.mamoe.mirai.message.MessageSourceSerializer
|
import net.mamoe.mirai.message.MessageSourceSerializerImpl
|
||||||
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutFriend
|
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutFriend
|
||||||
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutGroup
|
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutGroup
|
||||||
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutTemp
|
import net.mamoe.mirai.message.data.MessageSource.Key.isAboutTemp
|
||||||
@ -69,7 +69,7 @@ import net.mamoe.mirai.utils.safeCast
|
|||||||
*
|
*
|
||||||
* @see buildMessageSource 构造一个 [OfflineMessageSource]
|
* @see buildMessageSource 构造一个 [OfflineMessageSource]
|
||||||
*/
|
*/
|
||||||
@Serializable(MessageSourceSerializer::class)
|
@Serializable(MessageSourceSerializerImpl.Companion::class)
|
||||||
public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle {
|
public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle {
|
||||||
@ExperimentalMessageKey
|
@ExperimentalMessageKey
|
||||||
public final override val key: MessageKey<MessageSource>
|
public final override val key: MessageKey<MessageSource>
|
||||||
|
@ -25,7 +25,6 @@ import net.mamoe.mirai.internal.contact.*
|
|||||||
import net.mamoe.mirai.internal.message.*
|
import net.mamoe.mirai.internal.message.*
|
||||||
import net.mamoe.mirai.internal.network.highway.HighwayHelper
|
import net.mamoe.mirai.internal.network.highway.HighwayHelper
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.jce.SvcDevLoginInfo
|
import net.mamoe.mirai.internal.network.protocol.data.jce.SvcDevLoginInfo
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.LongMsg
|
import net.mamoe.mirai.internal.network.protocol.data.proto.LongMsg
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.*
|
import net.mamoe.mirai.internal.network.protocol.packet.chat.*
|
||||||
import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.PttStore
|
import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.PttStore
|
||||||
@ -40,7 +39,6 @@ import net.mamoe.mirai.message.data.Image.Key.FRIEND_IMAGE_ID_REGEX_2
|
|||||||
import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX
|
import net.mamoe.mirai.message.data.Image.Key.GROUP_IMAGE_ID_REGEX
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
import net.mamoe.mirai.utils.ExternalResource.Companion.toExternalResource
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.random.Random
|
import kotlin.random.Random
|
||||||
|
|
||||||
@ -54,6 +52,15 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
|
|||||||
Message.Serializer.registerSerializer(OfflineGroupImage::class, OfflineGroupImage.serializer())
|
Message.Serializer.registerSerializer(OfflineGroupImage::class, OfflineGroupImage.serializer())
|
||||||
Message.Serializer.registerSerializer(OfflineFriendImage::class, OfflineFriendImage.serializer())
|
Message.Serializer.registerSerializer(OfflineFriendImage::class, OfflineFriendImage.serializer())
|
||||||
Message.Serializer.registerSerializer(MarketFaceImpl::class, MarketFaceImpl.serializer())
|
Message.Serializer.registerSerializer(MarketFaceImpl::class, MarketFaceImpl.serializer())
|
||||||
|
Message.Serializer.registerSerializer(
|
||||||
|
OfflineMessageSourceImplData::class,
|
||||||
|
OfflineMessageSourceImplData.serializer()
|
||||||
|
)
|
||||||
|
|
||||||
|
Message.Serializer.registerSerializer(
|
||||||
|
MessageSourceFromGroupImpl::class,
|
||||||
|
MessageSourceFromGroupImpl.serializer()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -843,38 +850,8 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
|
|||||||
time: Int,
|
time: Int,
|
||||||
internalIds: IntArray,
|
internalIds: IntArray,
|
||||||
originalMessage: MessageChain
|
originalMessage: MessageChain
|
||||||
): OfflineMessageSource {
|
): OfflineMessageSource = OfflineMessageSourceImplData(
|
||||||
return object : OfflineMessageSource(), MessageSourceInternal {
|
kind, ids, botId, time, fromUin, targetUin, originalMessage, internalIds
|
||||||
override val kind: MessageSourceKind get() = kind
|
|
||||||
override val ids: IntArray get() = ids
|
|
||||||
override val botId: Long get() = botId
|
|
||||||
override val time: Int get() = time
|
|
||||||
override val fromId: Long get() = fromUin
|
|
||||||
override val targetId: Long get() = targetUin
|
|
||||||
override val originalMessage: MessageChain get() = originalMessage
|
|
||||||
override val sequenceIds: IntArray = ids
|
|
||||||
override val internalIds: IntArray = internalIds
|
|
||||||
|
|
||||||
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
|
||||||
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
|
|
||||||
|
|
||||||
override fun toJceData(): ImMsgBody.SourceMsg {
|
|
||||||
return ImMsgBody.SourceMsg(
|
|
||||||
origSeqs = sequenceIds,
|
|
||||||
senderUin = fromUin,
|
|
||||||
toUin = 0,
|
|
||||||
flag = 1,
|
|
||||||
elems = originalMessage.toRichTextElems(
|
|
||||||
null, //forGroup = kind == MessageSourceKind.GROUP,
|
|
||||||
withGeneralFlags = false
|
|
||||||
),
|
|
||||||
type = 0,
|
|
||||||
time = time,
|
|
||||||
pbReserve = EMPTY_BYTE_ARRAY,
|
|
||||||
srcMsg = EMPTY_BYTE_ARRAY
|
|
||||||
)
|
)
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.internal.message
|
package net.mamoe.mirai.internal.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
import net.mamoe.mirai.Bot
|
import net.mamoe.mirai.Bot
|
||||||
import net.mamoe.mirai.contact.Friend
|
import net.mamoe.mirai.contact.Friend
|
||||||
import net.mamoe.mirai.contact.Member
|
import net.mamoe.mirai.contact.Member
|
||||||
@ -22,6 +24,7 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
|
|||||||
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
|
import net.mamoe.mirai.internal.network.protocol.packet.EMPTY_BYTE_ARRAY
|
||||||
import net.mamoe.mirai.internal.utils._miraiContentToString
|
import net.mamoe.mirai.internal.utils._miraiContentToString
|
||||||
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
|
||||||
|
import net.mamoe.mirai.message.MessageSourceSerializerImpl
|
||||||
import net.mamoe.mirai.message.data.Message
|
import net.mamoe.mirai.message.data.Message
|
||||||
import net.mamoe.mirai.message.data.MessageChain
|
import net.mamoe.mirai.message.data.MessageChain
|
||||||
import net.mamoe.mirai.message.data.MessageSource
|
import net.mamoe.mirai.message.data.MessageSource
|
||||||
@ -32,12 +35,17 @@ import net.mamoe.mirai.utils.mapToIntArray
|
|||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
internal interface MessageSourceInternal {
|
internal interface MessageSourceInternal {
|
||||||
|
@Transient
|
||||||
val sequenceIds: IntArray
|
val sequenceIds: IntArray
|
||||||
|
|
||||||
|
@Transient
|
||||||
val internalIds: IntArray // randomId
|
val internalIds: IntArray // randomId
|
||||||
|
|
||||||
@Deprecated("don't use this internally. Use sequenceId or random instead.", level = DeprecationLevel.ERROR)
|
@Deprecated("don't use this internally. Use sequenceId or random instead.", level = DeprecationLevel.ERROR)
|
||||||
|
@Transient
|
||||||
val ids: IntArray
|
val ids: IntArray
|
||||||
|
|
||||||
|
@Transient
|
||||||
val isRecalledOrPlanned: AtomicBoolean
|
val isRecalledOrPlanned: AtomicBoolean
|
||||||
|
|
||||||
fun toJceData(): ImMsgBody.SourceMsg
|
fun toJceData(): ImMsgBody.SourceMsg
|
||||||
@ -148,10 +156,14 @@ internal class MessageSourceFromTempImpl(
|
|||||||
override fun toJceData(): ImMsgBody.SourceMsg = jceData
|
override fun toJceData(): ImMsgBody.SourceMsg = jceData
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Serializable(MessageSourceFromGroupImpl.Serializer::class)
|
||||||
internal data class MessageSourceFromGroupImpl(
|
internal data class MessageSourceFromGroupImpl(
|
||||||
override val bot: Bot,
|
override val bot: Bot,
|
||||||
private val msg: List<MsgComm.Msg>
|
private val msg: List<MsgComm.Msg>
|
||||||
) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal {
|
) : OnlineMessageSource.Incoming.FromGroup(), MessageSourceInternal {
|
||||||
|
object Serializer : MessageSourceSerializerImpl("net.mamoe.mirai.internal.message.MessageSourceFromGroupImpl")
|
||||||
|
|
||||||
|
@Transient
|
||||||
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
|
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
|
||||||
override val sequenceIds: IntArray get() = msg.mapToIntArray { it.msgHead.msgSeq }
|
override val sequenceIds: IntArray get() = msg.mapToIntArray { it.msgHead.msgSeq }
|
||||||
override val internalIds: IntArray get() = msg.mapToIntArray { it.msgBody.richText.attr!!.random }
|
override val internalIds: IntArray get() = msg.mapToIntArray { it.msgBody.richText.attr!!.random }
|
||||||
|
@ -11,6 +11,8 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.internal.message
|
package net.mamoe.mirai.internal.message
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
import kotlinx.serialization.Transient
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
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.MsgComm
|
||||||
import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
|
import net.mamoe.mirai.internal.network.protocol.data.proto.SourceMsg
|
||||||
@ -22,6 +24,70 @@ import net.mamoe.mirai.message.data.OfflineMessageSource
|
|||||||
import net.mamoe.mirai.utils.mapToIntArray
|
import net.mamoe.mirai.utils.mapToIntArray
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
internal data class OfflineMessageSourceImplData(
|
||||||
|
override val kind: MessageSourceKind,
|
||||||
|
override val ids: IntArray,
|
||||||
|
override val botId: Long,
|
||||||
|
override val time: Int,
|
||||||
|
override val fromId: Long,
|
||||||
|
override val targetId: Long,
|
||||||
|
override val originalMessage: MessageChain,
|
||||||
|
override val internalIds: IntArray,
|
||||||
|
) : OfflineMessageSource(), MessageSourceInternal {
|
||||||
|
override val sequenceIds: IntArray get() = ids
|
||||||
|
|
||||||
|
@Transient
|
||||||
|
@Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||||
|
override var isRecalledOrPlanned: AtomicBoolean = AtomicBoolean(false)
|
||||||
|
|
||||||
|
override fun toJceData(): ImMsgBody.SourceMsg {
|
||||||
|
return ImMsgBody.SourceMsg(
|
||||||
|
origSeqs = sequenceIds,
|
||||||
|
senderUin = fromId,
|
||||||
|
toUin = 0,
|
||||||
|
flag = 1,
|
||||||
|
elems = originalMessage.toRichTextElems(
|
||||||
|
null, //forGroup = kind == MessageSourceKind.GROUP,
|
||||||
|
withGeneralFlags = false
|
||||||
|
),
|
||||||
|
type = 0,
|
||||||
|
time = time,
|
||||||
|
pbReserve = net.mamoe.mirai.internal.EMPTY_BYTE_ARRAY,
|
||||||
|
srcMsg = net.mamoe.mirai.internal.EMPTY_BYTE_ARRAY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as OfflineMessageSourceImplData
|
||||||
|
|
||||||
|
if (kind != other.kind) return false
|
||||||
|
if (!ids.contentEquals(other.ids)) return false
|
||||||
|
if (botId != other.botId) return false
|
||||||
|
if (time != other.time) return false
|
||||||
|
if (fromId != other.fromId) return false
|
||||||
|
if (targetId != other.targetId) return false
|
||||||
|
if (originalMessage != other.originalMessage) return false
|
||||||
|
if (!internalIds.contentEquals(other.internalIds)) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = kind.hashCode()
|
||||||
|
result = 31 * result + ids.contentHashCode()
|
||||||
|
result = 31 * result + botId.hashCode()
|
||||||
|
result = 31 * result + time
|
||||||
|
result = 31 * result + fromId.hashCode()
|
||||||
|
result = 31 * result + targetId.hashCode()
|
||||||
|
result = 31 * result + originalMessage.hashCode()
|
||||||
|
result = 31 * result + internalIds.contentHashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal class OfflineMessageSourceImplByMsg(
|
internal class OfflineMessageSourceImplByMsg(
|
||||||
// from other sources' originalMessage
|
// from other sources' originalMessage
|
||||||
|
@ -563,7 +563,7 @@ internal class ImMsgBody : ProtoBuf {
|
|||||||
) : ProtoBuf
|
) : ProtoBuf
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
internal class MarketFace(
|
internal data class MarketFace(
|
||||||
@ProtoNumber(1) @JvmField val faceName: ByteArray = EMPTY_BYTE_ARRAY,
|
@ProtoNumber(1) @JvmField val faceName: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
@ProtoNumber(2) @JvmField val itemType: Int = 0,
|
@ProtoNumber(2) @JvmField val itemType: Int = 0,
|
||||||
@ProtoNumber(3) @JvmField val faceInfo: Int = 0,
|
@ProtoNumber(3) @JvmField val faceInfo: Int = 0,
|
||||||
@ -577,7 +577,48 @@ internal class ImMsgBody : ProtoBuf {
|
|||||||
@ProtoNumber(11) @JvmField val imageHeight: Int = 0,
|
@ProtoNumber(11) @JvmField val imageHeight: Int = 0,
|
||||||
@ProtoNumber(12) @JvmField val mobileParam: ByteArray = EMPTY_BYTE_ARRAY,
|
@ProtoNumber(12) @JvmField val mobileParam: ByteArray = EMPTY_BYTE_ARRAY,
|
||||||
@ProtoNumber(13) @JvmField val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
|
@ProtoNumber(13) @JvmField val pbReserve: ByteArray = EMPTY_BYTE_ARRAY
|
||||||
) : ProtoBuf
|
) : ProtoBuf {
|
||||||
|
@Suppress("DuplicatedCode")
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (javaClass != other?.javaClass) return false
|
||||||
|
|
||||||
|
other as MarketFace
|
||||||
|
|
||||||
|
if (!faceName.contentEquals(other.faceName)) return false
|
||||||
|
if (itemType != other.itemType) return false
|
||||||
|
if (faceInfo != other.faceInfo) return false
|
||||||
|
if (!faceId.contentEquals(other.faceId)) return false
|
||||||
|
if (tabId != other.tabId) return false
|
||||||
|
if (subType != other.subType) return false
|
||||||
|
if (!key.contentEquals(other.key)) return false
|
||||||
|
if (!param.contentEquals(other.param)) return false
|
||||||
|
if (mediaType != other.mediaType) return false
|
||||||
|
if (imageWidth != other.imageWidth) return false
|
||||||
|
if (imageHeight != other.imageHeight) return false
|
||||||
|
if (!mobileParam.contentEquals(other.mobileParam)) return false
|
||||||
|
if (!pbReserve.contentEquals(other.pbReserve)) return false
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
var result = faceName.contentHashCode()
|
||||||
|
result = 31 * result + itemType
|
||||||
|
result = 31 * result + faceInfo
|
||||||
|
result = 31 * result + faceId.contentHashCode()
|
||||||
|
result = 31 * result + tabId
|
||||||
|
result = 31 * result + subType
|
||||||
|
result = 31 * result + key.contentHashCode()
|
||||||
|
result = 31 * result + param.contentHashCode()
|
||||||
|
result = 31 * result + mediaType
|
||||||
|
result = 31 * result + imageWidth
|
||||||
|
result = 31 * result + imageHeight
|
||||||
|
result = 31 * result + mobileParam.contentHashCode()
|
||||||
|
result = 31 * result + pbReserve.contentHashCode()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
internal class MarketTrans(
|
internal class MarketTrans(
|
||||||
|
@ -13,16 +13,19 @@ import kotlinx.serialization.KSerializer
|
|||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
import net.mamoe.mirai.Mirai
|
import net.mamoe.mirai.Mirai
|
||||||
|
import net.mamoe.mirai.internal.message.MarketFaceImpl
|
||||||
|
import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody
|
||||||
import net.mamoe.mirai.message.data.*
|
import net.mamoe.mirai.message.data.*
|
||||||
import org.junit.jupiter.api.BeforeAll
|
import org.junit.jupiter.api.BeforeAll
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
internal class MessageSerializationTest {
|
internal class MessageSerializationTest {
|
||||||
private val module = Message.Serializer.serializersModule
|
private val module get() = Message.Serializer.serializersModule
|
||||||
private val format = Json {
|
private val format
|
||||||
|
get() = Json {
|
||||||
serializersModule = module
|
serializersModule = module
|
||||||
useArrayPolymorphism = false
|
useArrayPolymorphism = false // ?
|
||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T : Any> T.serialize(serializer: KSerializer<T> = module.serializer()): String {
|
private inline fun <reified T : Any> T.serialize(serializer: KSerializer<T> = module.serializer()): String {
|
||||||
@ -34,23 +37,57 @@ internal class MessageSerializationTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private inline fun <reified T : Any> testSerialization(t: T, serializer: KSerializer<T> = module.serializer()) {
|
private inline fun <reified T : Any> testSerialization(t: T, serializer: KSerializer<T> = module.serializer()) {
|
||||||
|
val deserialized = t.serialize(serializer).deserialize(serializer)
|
||||||
assertEquals(
|
assertEquals(
|
||||||
t,
|
t,
|
||||||
t.serialize(serializer).deserialize(serializer),
|
deserialized,
|
||||||
message = "serialized string: ${t.serialize(serializer)}"
|
message = "serialized string: ${t.serialize(serializer)}\ndeserialized string: ${
|
||||||
|
deserialized.serialize(
|
||||||
|
serializer
|
||||||
|
)
|
||||||
|
}\n"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private val image = Image("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai")
|
||||||
private val testMessageContentInstances: Array<out MessageContent> = arrayOf(
|
private val testMessageContentInstances: Array<out MessageContent> = arrayOf(
|
||||||
PlainText("test"),
|
PlainText("test"),
|
||||||
At(123456),
|
At(123456),
|
||||||
AtAll,
|
AtAll,
|
||||||
Image("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai"),
|
image,
|
||||||
|
image.toForwardMessage(1L, "test"),
|
||||||
|
VipFace(VipFace.AiXin, 1),
|
||||||
|
PokeMessage.BaoBeiQiu,
|
||||||
|
Face(Face.AI_NI),
|
||||||
|
MarketFaceImpl(ImMsgBody.MarketFace()),
|
||||||
|
image.flash(),
|
||||||
|
)
|
||||||
|
|
||||||
|
private val emptySource = Mirai.constructMessageSource(
|
||||||
|
1L,
|
||||||
|
MessageSourceKind.FRIEND,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
intArrayOf(1),
|
||||||
|
1,
|
||||||
|
intArrayOf(1),
|
||||||
|
messageChainOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
|
||||||
private val testConstrainSingleMessageInstances: Array<out ConstrainSingle> = arrayOf(
|
private val testConstrainSingleMessageInstances: Array<out ConstrainSingle> = arrayOf(
|
||||||
LongMessage("content", "resId")
|
LongMessage("content", "resId"),
|
||||||
|
Mirai.constructMessageSource(
|
||||||
|
1L,
|
||||||
|
MessageSourceKind.FRIEND,
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
intArrayOf(1),
|
||||||
|
1,
|
||||||
|
intArrayOf(1),
|
||||||
|
messageChainOf(emptySource, image)
|
||||||
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
Loading…
Reference in New Issue
Block a user