diff --git a/mirai-core-api/compatibility-validation/android/api/android.api b/mirai-core-api/compatibility-validation/android/api/android.api index 97e66cd17b..baa913bad2 100644 --- a/mirai-core-api/compatibility-validation/android/api/android.api +++ b/mirai-core-api/compatibility-validation/android/api/android.api @@ -1182,10 +1182,9 @@ public final class net/mamoe/mirai/contact/roaming/RoamingMessageFilter$Companio public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessages { public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow; - public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static synthetic fun getAllMessages$suspendImpl (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getAllMessagesStream ()Ljava/util/stream/Stream; public fun getAllMessagesStream (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getAllMessagesStream (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Ljava/util/stream/Stream; @@ -1193,6 +1192,9 @@ public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessages public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Ljava/util/stream/Stream; public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun getAllMessagesStream$suspendImpl (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun getMessagesBefore (Ljava/lang/Integer;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lnet/mamoe/mirai/utils/Streamable; + public abstract fun getMessagesBefore (Ljava/lang/Integer;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun getMessagesBefore$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Ljava/lang/Integer;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow; public abstract fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun getMessagesIn$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; @@ -4575,7 +4577,7 @@ public final class net/mamoe/mirai/message/data/MessageOriginKind$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public abstract class net/mamoe/mirai/message/data/MessageSource : net/mamoe/mirai/message/data/ConstrainSingle, net/mamoe/mirai/message/data/Message, net/mamoe/mirai/message/data/MessageMetadata { +public abstract class net/mamoe/mirai/message/data/MessageSource : net/mamoe/mirai/message/data/ConstrainSingle, net/mamoe/mirai/message/data/Message, net/mamoe/mirai/message/data/MessageMetadata, net/mamoe/mirai/message/source/identity/FullMessageIdentity { public static final field Key Lnet/mamoe/mirai/message/data/MessageSource$Key; public static final field SERIAL_NAME Ljava/lang/String; public abstract fun getBotId ()J @@ -5409,6 +5411,99 @@ public final class net/mamoe/mirai/message/data/XmlMessageBuilder$ItemBuilder { public final class net/mamoe/mirai/message/data/visitor/MessageVisitorKt { } +public abstract interface class net/mamoe/mirai/message/source/identity/FullMessageIdentity : net/mamoe/mirai/message/source/identity/MessageIdentity { + public fun convertToRawFullMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity; + public abstract fun getFromId ()J + public abstract fun getKind ()Lnet/mamoe/mirai/message/data/MessageSourceKind; + public abstract fun getTargetId ()J +} + +public final class net/mamoe/mirai/message/source/identity/FullyMessageIdentitySerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/FullyMessageIdentitySerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/FullMessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/FullMessageIdentity;)V +} + +public abstract interface class net/mamoe/mirai/message/source/identity/MessageIdentity { + public fun convertToRawMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity; + public abstract fun getIds ()[I + public abstract fun getInternalIds ()[I + public abstract fun getTime ()I +} + +public final class net/mamoe/mirai/message/source/identity/MessageIdentitySerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/MessageIdentitySerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/MessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/MessageIdentity;)V +} + +public final class net/mamoe/mirai/message/source/identity/RawFullMessageIdentity : net/mamoe/mirai/message/source/identity/FullMessageIdentity { + public static final field Companion Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity$Companion; + public synthetic fun (I[I[IIJJLnet/mamoe/mirai/message/data/MessageSourceKind;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun ([I[IIJJLnet/mamoe/mirai/message/data/MessageSourceKind;)V + public fun convertToRawFullMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity; + public fun equals (Ljava/lang/Object;)Z + public fun getFromId ()J + public fun getIds ()[I + public fun getInternalIds ()[I + public fun getKind ()Lnet/mamoe/mirai/message/data/MessageSourceKind; + public fun getTargetId ()J + public fun getTime ()I + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final fun write$Self (Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class net/mamoe/mirai/message/source/identity/RawFullMessageIdentity$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity$$serializer; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class net/mamoe/mirai/message/source/identity/RawFullMessageIdentity$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class net/mamoe/mirai/message/source/identity/RawMessageIdentity : net/mamoe/mirai/message/source/identity/MessageIdentity { + public static final field Companion Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity$Companion; + public synthetic fun (I[I[IILkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun ([I[II)V + public fun convertToRawMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity; + public fun equals (Ljava/lang/Object;)Z + public fun getIds ()[I + public fun getInternalIds ()[I + public fun getTime ()I + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final fun write$Self (Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class net/mamoe/mirai/message/source/identity/RawMessageIdentity$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity$$serializer; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class net/mamoe/mirai/message/source/identity/RawMessageIdentity$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class net/mamoe/mirai/network/BotAuthorizationException : net/mamoe/mirai/network/LoginFailedException { public final fun getAuthorization ()Lnet/mamoe/mirai/auth/BotAuthorization; } diff --git a/mirai-core-api/compatibility-validation/jvm/api/jvm.api b/mirai-core-api/compatibility-validation/jvm/api/jvm.api index 67b41a3ddb..90a824eaf9 100644 --- a/mirai-core-api/compatibility-validation/jvm/api/jvm.api +++ b/mirai-core-api/compatibility-validation/jvm/api/jvm.api @@ -1182,10 +1182,9 @@ public final class net/mamoe/mirai/contact/roaming/RoamingMessageFilter$Companio public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessages { public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow; - public fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public abstract fun getAllMessages (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; public static synthetic fun getAllMessages$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; - public static synthetic fun getAllMessages$suspendImpl (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getAllMessagesStream ()Ljava/util/stream/Stream; public fun getAllMessagesStream (Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public fun getAllMessagesStream (Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Ljava/util/stream/Stream; @@ -1193,6 +1192,9 @@ public abstract interface class net/mamoe/mirai/contact/roaming/RoamingMessages public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Ljava/util/stream/Stream; public static synthetic fun getAllMessagesStream$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public static synthetic fun getAllMessagesStream$suspendImpl (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public fun getMessagesBefore (Ljava/lang/Integer;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lnet/mamoe/mirai/utils/Streamable; + public abstract fun getMessagesBefore (Ljava/lang/Integer;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; + public static synthetic fun getMessagesBefore$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;Ljava/lang/Integer;Lnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;ILjava/lang/Object;)Ljava/lang/Object; public fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;)Lkotlinx/coroutines/flow/Flow; public abstract fun getMessagesIn (JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object; public static synthetic fun getMessagesIn$default (Lnet/mamoe/mirai/contact/roaming/RoamingMessages;JJLnet/mamoe/mirai/contact/roaming/RoamingMessageFilter;ILjava/lang/Object;)Lkotlinx/coroutines/flow/Flow; @@ -4575,7 +4577,7 @@ public final class net/mamoe/mirai/message/data/MessageOriginKind$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public abstract class net/mamoe/mirai/message/data/MessageSource : net/mamoe/mirai/message/data/ConstrainSingle, net/mamoe/mirai/message/data/Message, net/mamoe/mirai/message/data/MessageMetadata { +public abstract class net/mamoe/mirai/message/data/MessageSource : net/mamoe/mirai/message/data/ConstrainSingle, net/mamoe/mirai/message/data/Message, net/mamoe/mirai/message/data/MessageMetadata, net/mamoe/mirai/message/source/identity/FullMessageIdentity { public static final field Key Lnet/mamoe/mirai/message/data/MessageSource$Key; public static final field SERIAL_NAME Ljava/lang/String; public abstract fun getBotId ()J @@ -5409,6 +5411,99 @@ public final class net/mamoe/mirai/message/data/XmlMessageBuilder$ItemBuilder { public final class net/mamoe/mirai/message/data/visitor/MessageVisitorKt { } +public abstract interface class net/mamoe/mirai/message/source/identity/FullMessageIdentity : net/mamoe/mirai/message/source/identity/MessageIdentity { + public fun convertToRawFullMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity; + public abstract fun getFromId ()J + public abstract fun getKind ()Lnet/mamoe/mirai/message/data/MessageSourceKind; + public abstract fun getTargetId ()J +} + +public final class net/mamoe/mirai/message/source/identity/FullyMessageIdentitySerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/FullyMessageIdentitySerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/FullMessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/FullMessageIdentity;)V +} + +public abstract interface class net/mamoe/mirai/message/source/identity/MessageIdentity { + public fun convertToRawMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity; + public abstract fun getIds ()[I + public abstract fun getInternalIds ()[I + public abstract fun getTime ()I +} + +public final class net/mamoe/mirai/message/source/identity/MessageIdentitySerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/MessageIdentitySerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/MessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/MessageIdentity;)V +} + +public final class net/mamoe/mirai/message/source/identity/RawFullMessageIdentity : net/mamoe/mirai/message/source/identity/FullMessageIdentity { + public static final field Companion Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity$Companion; + public synthetic fun (I[I[IIJJLnet/mamoe/mirai/message/data/MessageSourceKind;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun ([I[IIJJLnet/mamoe/mirai/message/data/MessageSourceKind;)V + public fun convertToRawFullMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity; + public fun equals (Ljava/lang/Object;)Z + public fun getFromId ()J + public fun getIds ()[I + public fun getInternalIds ()[I + public fun getKind ()Lnet/mamoe/mirai/message/data/MessageSourceKind; + public fun getTargetId ()J + public fun getTime ()I + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final fun write$Self (Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class net/mamoe/mirai/message/source/identity/RawFullMessageIdentity$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity$$serializer; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/RawFullMessageIdentity;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class net/mamoe/mirai/message/source/identity/RawFullMessageIdentity$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + +public final class net/mamoe/mirai/message/source/identity/RawMessageIdentity : net/mamoe/mirai/message/source/identity/MessageIdentity { + public static final field Companion Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity$Companion; + public synthetic fun (I[I[IILkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun ([I[II)V + public fun convertToRawMessageIdentity ()Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity; + public fun equals (Ljava/lang/Object;)Z + public fun getIds ()[I + public fun getInternalIds ()[I + public fun getTime ()I + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final fun write$Self (Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class net/mamoe/mirai/message/source/identity/RawMessageIdentity$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity$$serializer; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lnet/mamoe/mirai/message/source/identity/RawMessageIdentity;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class net/mamoe/mirai/message/source/identity/RawMessageIdentity$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; +} + public final class net/mamoe/mirai/network/BotAuthorizationException : net/mamoe/mirai/network/LoginFailedException { public final fun getAuthorization ()Lnet/mamoe/mirai/auth/BotAuthorization; } diff --git a/mirai-core-api/src/commonMain/kotlin/contact/roaming/RoamingMessages.kt b/mirai-core-api/src/commonMain/kotlin/contact/roaming/RoamingMessages.kt index fd5e7db4a5..56f757bac2 100644 --- a/mirai-core-api/src/commonMain/kotlin/contact/roaming/RoamingMessages.kt +++ b/mirai-core-api/src/commonMain/kotlin/contact/roaming/RoamingMessages.kt @@ -12,6 +12,8 @@ package net.mamoe.mirai.contact.roaming import kotlinx.coroutines.flow.Flow import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageSource +import net.mamoe.mirai.message.data.OnlineMessageSource +import net.mamoe.mirai.utils.Streamable /** * 漫游消息记录管理器. 可通过 [RoamingSupported.roamingMessages] 获得. @@ -48,6 +50,31 @@ public expect interface RoamingMessages { filter: RoamingMessageFilter? = null ): Flow + /** + * 查询指定消息之前的消息记录 + * + * 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息. + * 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回. + * + * 注意, 返回的消息记录既包含机器人发送给目标用户的消息, 也包含目标用户发送给机器人的消息. + * 可通过 [MessageChain] 获取 [MessageSource] (用法为 `messageChain.source`), 判断 [MessageSource.fromId] (发送人). + * 消息的其他*元数据*信息也要通过 [MessageSource] 获取 (如 [MessageSource.time] 获取时间). + * + * 若只需要获取单向消息 (机器人发送给目标用户的消息或反之), 可使用 [RoamingMessageFilter.SENT] 或 [RoamingMessageFilter.RECEIVED] 作为 [filter] 参数传递. + * + * 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响. + * + * @param messageId 消息序列号,请查看 [MessageSource.ids], 一般为 [OnlineMessageSource] 的序列号。 + * 为 `null` 时从最近一条消息开始获取且包含该消息. + * @param filter 过滤器. + * @since 2.15 + * @see MessageSource + */ + public suspend fun getMessagesBefore( + messageId: Int? = null, + filter: RoamingMessageFilter? = null + ): Streamable + /** * 查询所有漫游消息记录. * @@ -64,7 +91,7 @@ public expect interface RoamingMessages { * * @param filter 过滤器. */ - public open suspend fun getAllMessages( + public suspend fun getAllMessages( filter: RoamingMessageFilter? = null ): Flow } \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt b/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt index c4c8fdf348..e35371aa18 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/MessageSource.kt @@ -34,13 +34,10 @@ import net.mamoe.mirai.message.action.AsyncRecallResult import net.mamoe.mirai.message.data.MessageSource.Key.quote import net.mamoe.mirai.message.data.MessageSource.Key.recall import net.mamoe.mirai.message.data.visitor.MessageVisitor +import net.mamoe.mirai.message.source.identity.FullMessageIdentity import net.mamoe.mirai.utils.DeprecatedSinceMirai import net.mamoe.mirai.utils.MiraiInternalApi import net.mamoe.mirai.utils.safeCast -import kotlin.jvm.JvmMultifileClass -import kotlin.jvm.JvmName -import kotlin.jvm.JvmStatic -import kotlin.jvm.JvmSynthetic /** * 表示聊天中的一条消息的定位信息, 即消息源. @@ -128,7 +125,7 @@ import kotlin.jvm.JvmSynthetic */ @Suppress("DEPRECATION") @Serializable(MessageSource.Serializer::class) -public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { +public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle, FullMessageIdentity { public final override val key: MessageKey get() = Key @@ -152,7 +149,7 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { * * [internalIds] 与 [ids] 以数组下标对应. */ - public abstract val ids: IntArray + public abstract override val ids: IntArray /** * 内部 ids. **仅用于协议模块使用** @@ -165,15 +162,12 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { * * @see ids */ - public abstract val internalIds: IntArray + public abstract override val internalIds: IntArray /** * 发送时间时间戳, 单位为秒. - * - * 自 2.8.0 起, 时间戳为服务器时区 (UTC+8). - * 在 2.8.0 以前, 时间戳可能来自服务器 (UTC+8), 也可能来自 mirai (本地), 且无法保证两者时间同步. */ - public abstract val time: Int + public abstract override val time: Int /** * 发送人用户 ID. @@ -182,7 +176,7 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { * - 当 [OnlineMessageSource.Incoming] 时为发信 [来源用户][User.id] 或 [群][Group.id] * - 当 [OfflineMessageSource] 时取决于 [OfflineMessageSource.kind] */ - public abstract val fromId: Long + public abstract override val fromId: Long /** * 消息发送目标用户或群号码. @@ -191,7 +185,7 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { * - 当 [OnlineMessageSource.Incoming] 时为 [机器人][Bot.id] * - 当 [OfflineMessageSource] 时取决于 [OfflineMessageSource.kind] */ - public abstract val targetId: Long // groupCode / friendUin / memberUin + public abstract override val targetId: Long // groupCode / friendUin / memberUin /** * 该消息源指向的原消息的内容. @@ -215,7 +209,7 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle { * * @since 2.15 */ - public abstract val kind: MessageSourceKind + public abstract override val kind: MessageSourceKind public abstract override fun toString(): String diff --git a/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.data.kt b/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.data.kt new file mode 100644 index 0000000000..4d5aba129d --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.data.kt @@ -0,0 +1,89 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.message.source.identity + +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import net.mamoe.mirai.message.data.MessageSourceKind + +@Serializable +@SerialName("MessageIdentity") +public class RawMessageIdentity( + override val ids: IntArray, + override val internalIds: IntArray, + override val time: Int, +) : MessageIdentity { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is RawMessageIdentity) return false + + if (!ids.contentEquals(other.ids)) return false + if (!internalIds.contentEquals(other.internalIds)) return false + return time == other.time + } + + override fun hashCode(): Int { + var result = ids.contentHashCode() + result = 31 * result + internalIds.contentHashCode() + result = 31 * result + time + return result + } + + override fun convertToRawMessageIdentity(): RawMessageIdentity { + return this + } + + override fun toString(): String { + return "[mirai:message-identity:ids=${ids.contentToString()}, internalIds=${internalIds.contentToString()}, time=$time]" + } +} + +@Serializable +@SerialName("FullMessageIdentity") +public class RawFullMessageIdentity( + override val ids: IntArray, + override val internalIds: IntArray, + override val time: Int, + override val fromId: Long, + override val targetId: Long, + override val kind: MessageSourceKind, +) : FullMessageIdentity { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is RawFullMessageIdentity) return false + + if (!ids.contentEquals(other.ids)) return false + if (!internalIds.contentEquals(other.internalIds)) return false + if (time != other.time) return false + if (fromId != other.fromId) return false + if (targetId != other.targetId) return false + return kind == other.kind + } + + override fun hashCode(): Int { + var result = ids.contentHashCode() + result = 31 * result + internalIds.contentHashCode() + result = 31 * result + time + result = 31 * result + fromId.hashCode() + result = 31 * result + targetId.hashCode() + result = 31 * result + kind.hashCode() + return result + } + + override fun convertToRawFullMessageIdentity(): RawFullMessageIdentity { + return this + } + + override fun toString(): String { + return "[mirai:message-identity:$kind, ids=${ids.contentToString()}, internalIds=${internalIds.contentToString()}, time=$time, from $fromId to $targetId]" + } +} + + diff --git a/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.kt b/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.kt new file mode 100644 index 0000000000..afd1b77405 --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.kt @@ -0,0 +1,108 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.message.source.identity + +import kotlinx.serialization.Serializable +import net.mamoe.mirai.message.data.MessageSourceKind +import net.mamoe.mirai.message.data.ids +import net.mamoe.mirai.utils.NotStableForInheritance +import org.jetbrains.annotations.ApiStatus + +/** + * 用于定位消息的消息凭证符 + * + * @since 2.16.0 + */ +@NotStableForInheritance +@ApiStatus.NonExtendable +@Serializable(MessageIdentitySerializer::class) +public interface MessageIdentity { + + /** + * 消息 ids (序列号). 在获取失败时 (概率很低) 为空数组. + * + * ### 顺序 + * 群消息的 id 由服务器维护. 好友消息的 id 由 mirai 维护. + * 此 id 不一定从 0 开始. + * + * - 在同一个群的消息中此值随每条消息递增 1, 但此行为由服务器决定, mirai 不保证自增顺序. + * - 在好友消息中无法保证每次都递增 1. 也可能会产生大幅跳过的情况. + * + * ### 多 ID 情况 + * 对于单条消息, [ids] 为单元素数组. 对于分片 (一种长消息处理机制) 消息, [ids] 将包含多元素. + * + * [internalIds] 与 [ids] 以数组下标对应. + */ + public val ids: IntArray + + /** + * 内部 ids. **仅用于协议模块使用** + * + * 值没有顺序, 也可能为 0, 取决于服务器是否提供. + * + * 在事件中和在引用中无法保证同一条消息的 [internalIds] 相同. + * + * [internalIds] 与 [ids] 以数组下标对应. + * + * @see ids + */ + public val internalIds: IntArray + + /** + * 发送时间时间戳, 单位为秒. + */ + public val time: Int + + + public fun convertToRawMessageIdentity(): RawMessageIdentity { + return RawMessageIdentity( + ids = this.ids, + internalIds = this.internalIds, + time = this.time, + ) + } +} + +/** + * 用于定位消息的消息凭证符, 附带发送者 id 和消息类型 + * + * @since 2.16.0 + */ +@NotStableForInheritance +@ApiStatus.NonExtendable +@Serializable(FullyMessageIdentitySerializer::class) +public interface FullMessageIdentity : MessageIdentity { + + /** + * 发送人用户 ID. + */ + public val fromId: Long // sender + + /** + * 消息发送目标用户或群号码. + */ + public val targetId: Long // groupCode / friendUin / memberUin + + /** + * 消息种类 + */ + public val kind: MessageSourceKind + + public fun convertToRawFullMessageIdentity(): RawFullMessageIdentity { + return RawFullMessageIdentity( + ids = ids, + internalIds = internalIds, + time = time, + fromId = fromId, + targetId = targetId, + kind = kind, + ) + } +} diff --git a/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.serializer.kt b/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.serializer.kt new file mode 100644 index 0000000000..a62f54e9cf --- /dev/null +++ b/mirai-core-api/src/commonMain/kotlin/message/source/identity/MessageIdentity.serializer.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.message.source.identity + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +public object MessageIdentitySerializer : KSerializer { + private val delegate = RawMessageIdentity.serializer() + + override val descriptor: SerialDescriptor + get() = delegate.descriptor + + override fun deserialize(decoder: Decoder): MessageIdentity { + return delegate.deserialize(decoder) + } + + override fun serialize(encoder: Encoder, value: MessageIdentity) { + delegate.serialize(encoder, value.convertToRawMessageIdentity()) + } +} + +public object FullyMessageIdentitySerializer : KSerializer { + private val delegate = RawFullMessageIdentity.serializer() + + override val descriptor: SerialDescriptor + get() = delegate.descriptor + + override fun deserialize(decoder: Decoder): FullMessageIdentity { + return delegate.deserialize(decoder) + } + + override fun serialize(encoder: Encoder, value: FullMessageIdentity) { + delegate.serialize(encoder, value.convertToRawFullMessageIdentity()) + } +} \ No newline at end of file diff --git a/mirai-core-api/src/jvmBaseMain/kotlin/contact/roaming/RoamingMessages.kt b/mirai-core-api/src/jvmBaseMain/kotlin/contact/roaming/RoamingMessages.kt index bb77500596..6dab6ebf7f 100644 --- a/mirai-core-api/src/jvmBaseMain/kotlin/contact/roaming/RoamingMessages.kt +++ b/mirai-core-api/src/jvmBaseMain/kotlin/contact/roaming/RoamingMessages.kt @@ -15,8 +15,10 @@ import kotlinx.coroutines.flow.Flow import me.him188.kotlin.jvm.blocking.bridge.JvmBlockingBridge import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageSource +import net.mamoe.mirai.message.data.OnlineMessageSource import net.mamoe.mirai.utils.JavaFriendlyAPI import net.mamoe.mirai.utils.JdkStreamSupport.toStream +import net.mamoe.mirai.utils.Streamable import java.util.stream.Stream @@ -56,6 +58,31 @@ public actual interface RoamingMessages { filter: RoamingMessageFilter? = null ): Flow + /** + * 查询指定消息之前的消息记录 + * + * 返回查询到的漫游消息记录, 顺序为由新到旧. 这些 [MessageChain] 与从事件中收到的消息链相似, 属于在线消息. + * 可从 [MessageChain] 获取 [MessageSource] 来确定发送人等相关信息, 也可以进行引用回复或撤回. + * + * 注意, 返回的消息记录既包含机器人发送给目标用户的消息, 也包含目标用户发送给机器人的消息. + * 可通过 [MessageChain] 获取 [MessageSource] (用法为 `messageChain.source`), 判断 [MessageSource.fromId] (发送人). + * 消息的其他*元数据*信息也要通过 [MessageSource] 获取 (如 [MessageSource.time] 获取时间). + * + * 若只需要获取单向消息 (机器人发送给目标用户的消息或反之), 可使用 [RoamingMessageFilter.SENT] 或 [RoamingMessageFilter.RECEIVED] 作为 [filter] 参数传递. + * + * 性能提示: 请在 [filter] 执行筛选, 若 [filter] 返回 `false` 则不会解析消息链, 这对本函数的处理速度有决定性影响. + * + * @param messageId 消息序列号,请查看 [MessageSource.ids], 一般为 [OnlineMessageSource] 的序列号。 + * 为 `null` 时从最近一条消息开始获取且包含该消息. + * @param filter 过滤器. + * @since 2.15 + * @see MessageSource + */ + public actual suspend fun getMessagesBefore( + messageId: Int?, + filter: RoamingMessageFilter? + ): Streamable + /** * 查询所有漫游消息记录. Java Stream 方法查看 [getAllMessagesStream]. * @@ -75,7 +102,7 @@ public actual interface RoamingMessages { @Suppress("ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS") // Keep JVM ABI public actual suspend fun getAllMessages( filter: RoamingMessageFilter? = null - ): Flow = getMessagesIn(0, Long.MAX_VALUE, filter) + ): Flow /** * 查询指定时间段内的漫游消息记录. Kotlin Flow 版本查看 [getMessagesIn]. @@ -125,5 +152,5 @@ public actual interface RoamingMessages { @JavaFriendlyAPI public suspend fun getAllMessagesStream( filter: RoamingMessageFilter? = null - ): Stream = getMessagesStream(0, Long.MAX_VALUE, filter) + ): Stream = getAllMessages().toStream() } \ No newline at end of file diff --git a/mirai-core-mock/src/database/MessageDatabase.kt b/mirai-core-mock/src/database/MessageDatabase.kt index 61612760e4..da4e03dd3a 100644 --- a/mirai-core-mock/src/database/MessageDatabase.kt +++ b/mirai-core-mock/src/database/MessageDatabase.kt @@ -46,6 +46,13 @@ public interface MessageDatabase { filter: RoamingMessageFilter ): Sequence + public fun queryMessageInfosBy( + subject: Long, kind: MessageSourceKind, + contact: Contact, + sequence: Long, + filter: RoamingMessageFilter + ): Sequence + /** * implementation note: 该方法可能同时被多个线程同时调用 */ diff --git a/mirai-core-mock/src/internal/contact/roaming/MockRoamingMessages.kt b/mirai-core-mock/src/internal/contact/roaming/MockRoamingMessages.kt index 7eede53669..955340ada0 100644 --- a/mirai-core-mock/src/internal/contact/roaming/MockRoamingMessages.kt +++ b/mirai-core-mock/src/internal/contact/roaming/MockRoamingMessages.kt @@ -11,6 +11,7 @@ package net.mamoe.mirai.mock.internal.contact.roaming import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.asFlow +import kotlinx.coroutines.flow.emptyFlow import net.mamoe.mirai.contact.Friend import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Stranger @@ -22,6 +23,7 @@ import net.mamoe.mirai.message.data.MessageSourceKind import net.mamoe.mirai.mock.internal.MockBotImpl import net.mamoe.mirai.mock.utils.mock import net.mamoe.mirai.utils.JavaFriendlyAPI +import net.mamoe.mirai.utils.Streamable import net.mamoe.mirai.utils.cast import java.util.stream.Stream import kotlin.streams.asStream @@ -37,6 +39,22 @@ internal class MockRoamingMessages( return getMsg(timeStart, timeEnd, filter).asFlow() } + override suspend fun getMessagesBefore( + messageId: Int?, + filter: RoamingMessageFilter? + ): Streamable { + return object : Streamable { + override fun asFlow(): Flow { + messageId ?: return emptyFlow() + return getMsg(messageId.toLong(), filter).asFlow() + } + } + } + + override suspend fun getAllMessages(filter: RoamingMessageFilter?): Flow { + return getMsg(0, Long.MAX_VALUE, filter).asFlow() + } + private fun getMsg( timeStart: Long, timeEnd: Long, @@ -58,6 +76,25 @@ internal class MockRoamingMessages( ).map { it.buildSource(contact.bot.mock()) + it.message } } + private fun getMsg( + sequence: Long, + filter: RoamingMessageFilter? + ): Sequence { + val msgDb = contact.bot.cast().msgDatabase + return msgDb.queryMessageInfosBy( + contact.id, + when (contact) { + is Friend -> MessageSourceKind.FRIEND + is Group -> MessageSourceKind.GROUP + is Stranger -> MessageSourceKind.STRANGER + else -> error(contact.javaClass.toString()) + }, + contact, + sequence, + filter ?: RoamingMessageFilter.ANY + ).map { it.buildSource(contact.bot.mock()) + it.message } + } + @JavaFriendlyAPI override suspend fun getMessagesStream( timeStart: Long, diff --git a/mirai-core-mock/src/internal/db/MsgDatabaseImpl.kt b/mirai-core-mock/src/internal/db/MsgDatabaseImpl.kt index 2bef81e7af..8df7c1bc0e 100644 --- a/mirai-core-mock/src/internal/db/MsgDatabaseImpl.kt +++ b/mirai-core-mock/src/internal/db/MsgDatabaseImpl.kt @@ -65,33 +65,34 @@ internal class MsgDatabaseImpl : MessageDatabase { ): Sequence { if (timeEnd < timeStart) return emptySequence() return sequence { - val rm = object : RoamingMessage { - override val contact: Contact get() = contact - override var sender: Long = -1 - override var target: Long = -1 - override var time: Long = -1 - override val ids: IntArray = intArrayOf(-1) - override val internalIds: IntArray = intArrayOf(-1) - } for (msgInfo in db) { if (msgInfo.kind != kind) continue if (msgInfo.time < timeStart) continue if (msgInfo.time > timeEnd) continue if (msgInfo.subject != subject) continue - rm.sender = msgInfo.sender - if (kind != MessageSourceKind.GROUP) { - if (msgInfo.sender == contact.id) { - rm.target = contact.bot.id - } else { - rm.target = msgInfo.subject - } - } else { - rm.target = msgInfo.subject + val rm = msgInfo.toRoamingMessage(contact) + + if (filter.invoke(rm)) { + yield(msgInfo) } - rm.time = msgInfo.time - rm.ids[0] = msgInfo.id - rm.internalIds[0] = msgInfo.internal + } + } + } + + override fun queryMessageInfosBy( + subject: Long, kind: MessageSourceKind, + contact: Contact, + sequence: Long, + filter: RoamingMessageFilter + ): Sequence { + return sequence { + var emitted = 0 + for (msgInfo in db) { + if (msgInfo.kind != kind) continue + if (msgInfo.subject != subject) continue + + val rm = msgInfo.toRoamingMessage(contact) if (filter.invoke(rm)) { yield(msgInfo) @@ -99,4 +100,27 @@ internal class MsgDatabaseImpl : MessageDatabase { } } } + + private fun MessageInfo.toRoamingMessage(contact: Contact): RoamingMessage { + val info = this + + return object : RoamingMessage { + override val contact: Contact = contact + override val sender: Long = info.sender + override val target: Long = + if (info.kind != MessageSourceKind.GROUP) { + if (info.sender == contact.id) { + contact.bot.id + } else { + info.subject + } + } else { + info.subject + } + override val time: Long = info.time + override val ids: IntArray = IntArray(1) { info.id } + override val internalIds: IntArray = IntArray(1) { info.internal } + + } + } } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/contact/roaming/RoamingMessagesImplGroup.kt b/mirai-core/src/commonMain/kotlin/contact/roaming/RoamingMessagesImplGroup.kt index 4745b29908..4a5f6d6600 100644 --- a/mirai-core/src/commonMain/kotlin/contact/roaming/RoamingMessagesImplGroup.kt +++ b/mirai-core/src/commonMain/kotlin/contact/roaming/RoamingMessagesImplGroup.kt @@ -9,78 +9,28 @@ package net.mamoe.mirai.internal.contact.roaming -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow import net.mamoe.mirai.contact.roaming.RoamingMessageFilter import net.mamoe.mirai.internal.contact.CommonGroupImpl -import net.mamoe.mirai.internal.message.toMessageChainOnline import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopManagement import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetGroupMsg import net.mamoe.mirai.message.data.MessageChain -import net.mamoe.mirai.message.data.MessageSourceKind internal class RoamingMessagesImplGroup( override val contact: CommonGroupImpl -) : AbstractRoamingMessages() { - private val bot get() = contact.bot - +) : SequenceBasedRoamingMessagesImpl() { override suspend fun getMessagesIn( timeStart: Long, timeEnd: Long, filter: RoamingMessageFilter? - ): Flow { - var currentSeq: Int = getLastMsgSeq() ?: return emptyFlow() - var lastOfferedSeq = -1 - - return flow { - while (true) { - val resp = contact.bot.network.sendAndExpect( - MessageSvcPbGetGroupMsg( - client = contact.bot.client, - groupUin = contact.uin, - messageSequence = currentSeq.toLong(), - count = 20 // maximum 20 - ) - ) - - if (resp is MessageSvcPbGetGroupMsg.Failed) break - resp as MessageSvcPbGetGroupMsg.Success // stupid smart cast - if (resp.msgElem.isEmpty()) break - - // the message may be sorted increasing by message time, - // if so, additional sortBy will not take cost. - val messageTimeSequence = resp.msgElem.asSequence().map { it.time } - - val maxTime = messageTimeSequence.max() - - - // we have fetched all messages - // note: maxTime = 0 means all fetched messages were recalled - if (maxTime < timeStart && maxTime != 0) break - - emitAll( - resp.msgElem.asSequence() - .filter { lastOfferedSeq == -1 || it.msgHead.msgSeq < lastOfferedSeq } - .filter { it.time in timeStart..timeEnd } - .sortedByDescending { it.msgHead.msgSeq } // Ensure caller receives newer messages first - .filter { filter.apply(it) } // Call filter after sort - .asFlow() - .map { listOf(it).toMessageChainOnline(bot, contact.id, MessageSourceKind.GROUP) } - ) - - currentSeq = resp.msgElem.first().msgHead.msgSeq - lastOfferedSeq = currentSeq - } - } - } - - private val MsgComm.Msg.time get() = msgHead.msgTime + ): Flow = getMessagesImpl( + preFilter = { maxTime -> maxTime >= timeStart || maxTime == 0 }, + preSortFilter = { msg -> msg.msgHead.msgTime in timeStart..timeEnd }, + filter = filter + ) - private fun RoamingMessageFilter?.apply( - it: MsgComm.Msg - ) = this?.invoke(createRoamingMessage(it, listOf())) != false - - private suspend fun getLastMsgSeq(): Int? { + override suspend fun getLastMsgSeq(): Int? { // Iterate from the newest message to find messages within [timeStart] and [timeEnd] val lastMsgSeqResp = bot.network.sendAndExpect( TroopManagement.GetGroupLastMsgSeq( @@ -94,4 +44,19 @@ internal class RoamingMessagesImplGroup( is TroopManagement.GetGroupLastMsgSeq.Response.Success -> lastMsgSeqResp.seq } } + + override suspend fun getMsg(seq: Int): List { + val resp = contact.bot.network.sendAndExpect( + MessageSvcPbGetGroupMsg( + client = contact.bot.client, + groupUin = contact.uin, + messageSequence = seq.toLong(), + count = 20 // maximum 20 + ) + ) + + if (resp is MessageSvcPbGetGroupMsg.Failed) return listOf() + resp as MessageSvcPbGetGroupMsg.Success // stupid smart cast + return resp.msgElem + } } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/contact/roaming/SequenceBasedRoamingMessagesImpl.kt b/mirai-core/src/commonMain/kotlin/contact/roaming/SequenceBasedRoamingMessagesImpl.kt new file mode 100644 index 0000000000..564a17e147 --- /dev/null +++ b/mirai-core/src/commonMain/kotlin/contact/roaming/SequenceBasedRoamingMessagesImpl.kt @@ -0,0 +1,95 @@ +/* + * Copyright 2019-2023 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/dev/LICENSE + */ + +package net.mamoe.mirai.internal.contact.roaming + +import kotlinx.coroutines.flow.* +import net.mamoe.mirai.contact.roaming.RoamingMessageFilter +import net.mamoe.mirai.internal.message.toMessageChainOnline +import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm +import net.mamoe.mirai.message.data.MessageChain +import net.mamoe.mirai.message.data.MessageSourceKind +import net.mamoe.mirai.utils.Streamable + +internal sealed class SequenceBasedRoamingMessagesImpl : AbstractRoamingMessages() { + internal val bot get() = contact.bot + override suspend fun getMessagesIn( + timeStart: Long, + timeEnd: Long, + filter: RoamingMessageFilter? + ): Flow { + error("not implemented in SequenceBasedRoamingMessage.") + } + + override suspend fun getMessagesBefore( + messageId: Int?, + filter: RoamingMessageFilter? + ): Streamable { + val flow = getMessagesImpl(messageId, preSortFilter = { true }, filter = filter) + return object : Streamable { + override fun asFlow(): Flow { + return flow + } + } + } + + override suspend fun getAllMessages( + filter: RoamingMessageFilter? + ): Flow = getMessagesBefore().asFlow() + + + /** + * get message sequences + * @param preFilter: filter before emitting message elements, break loop if false. + * use it to predict if we fetched all messages. param1 is time of newest message. + * @param preSortFilter: message element filter, param is msgElem + * @param filter: user-defined roaming message filter + */ + internal suspend fun getMessagesImpl( + initialSeq: Int? = null, + preFilter: (maxTime: Int) -> Boolean = { true }, + preSortFilter: (msg: MsgComm.Msg) -> Boolean, + filter: RoamingMessageFilter? + ): Flow { + var currentSeq: Int = initialSeq ?: getLastMsgSeq() ?: return emptyFlow() + var lastOfferedSeq = -1 + + return flow { + while (true) { + val msgElem = getMsg(currentSeq) + if (msgElem.isEmpty()) break + + // the message may be sorted increasing by message time, + // if so, additional sortBy will not take cost. + val maxTime = msgElem.asSequence().map { it.msgHead.msgTime }.max() + if (!preFilter(maxTime)) break + + emitAll( + msgElem.asSequence() + .filter { lastOfferedSeq == -1 || it.msgHead.msgSeq < lastOfferedSeq } + .filter(preSortFilter) + .sortedByDescending { it.msgHead.msgSeq } // Ensure caller receives newer messages first + .filter { filter.apply(it) } // Call filter after sort + .asFlow() + .map { listOf(it).toMessageChainOnline(bot, contact.id, MessageSourceKind.GROUP) } + ) + + currentSeq = msgElem.first().msgHead.msgSeq + lastOfferedSeq = currentSeq + } + } + } + + private fun RoamingMessageFilter?.apply(it: MsgComm.Msg) = + this?.invoke(createRoamingMessage(it, listOf())) != false + + internal abstract suspend fun getLastMsgSeq(): Int? + + internal abstract suspend fun getMsg(seq: Int): List +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/contact/roaming/TimeBasedRoamingMessagesImpl.kt b/mirai-core/src/commonMain/kotlin/contact/roaming/TimeBasedRoamingMessagesImpl.kt index 16bf47b79d..b056af9f6a 100644 --- a/mirai-core/src/commonMain/kotlin/contact/roaming/TimeBasedRoamingMessagesImpl.kt +++ b/mirai-core/src/commonMain/kotlin/contact/roaming/TimeBasedRoamingMessagesImpl.kt @@ -19,6 +19,7 @@ import net.mamoe.mirai.contact.roaming.RoamingMessageFilter import net.mamoe.mirai.internal.message.toMessageChainOnline import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.MessageSvcPbGetRoamMsgReq import net.mamoe.mirai.message.data.MessageChain +import net.mamoe.mirai.utils.Streamable internal sealed class TimeBasedRoamingMessagesImpl : AbstractRoamingMessages() { override suspend fun getMessagesIn( @@ -49,6 +50,17 @@ internal sealed class TimeBasedRoamingMessagesImpl : AbstractRoamingMessages() { } } + override suspend fun getAllMessages( + filter: RoamingMessageFilter? + ): Flow = getMessagesIn(0, Long.MAX_VALUE, filter) + + override suspend fun getMessagesBefore( + messageId: Int?, + filter: RoamingMessageFilter? + ): Streamable { + error("not implemented in TimeBasedRoamingMessage.") + } + abstract suspend fun requestRoamMsg( timeStart: Long, lastMessageTime: Long,