Redesign Message.Key. #693.

- `ConstrainSingle` now extends a more general type `SingleMessage` instead of `MessageMetadata` for extendability
- `Message.Key` moved to `ConstrainSingle.Key`
- Delete `companion object Key`s from duplicable messages
This commit is contained in:
Him188 2020-12-05 12:57:34 +08:00
parent 2717bd1dae
commit f6e9f306d4
19 changed files with 90 additions and 127 deletions

View File

@ -52,10 +52,7 @@ private constructor(
public override fun toString(): String = "[mirai:at:$target,$display]" public override fun toString(): String = "[mirai:at:$target,$display]"
public override fun contentToString(): String = this.display public override fun contentToString(): String = this.display
public companion object Key : Message.Key<At> { public companion object {
public override val typeName: String
get() = "At"
/** /**
* 构造一个 [At], 仅供内部使用, 否则可能造成消息无法发出的问题. * 构造一个 [At], 仅供内部使用, 否则可能造成消息无法发出的问题.
*/ */

View File

@ -30,11 +30,8 @@ private const val displayA = "@全体成员"
*/ */
@Serializable @Serializable
public object AtAll : public object AtAll :
Message.Key<AtAll>,
MessageContent, CodableMessage { MessageContent, CodableMessage {
public const val display: String = displayA public const val display: String = displayA
public override val typeName: String
get() = "AtAll"
@Suppress("SpellCheckingInspection") @Suppress("SpellCheckingInspection")
public override fun toString(): String = "[mirai:atall]" public override fun toString(): String = "[mirai:atall]"

View File

@ -60,7 +60,7 @@ public sealed class CustomMessage : SingleMessage {
* 应确保唯一且不变. * 应确保唯一且不变.
*/ */
public final override val typeName: String public final override val typeName: String
) : Message.Key<M> { ) : ConstrainSingle.Key<M> {
init { init {
@Suppress("LeakingThis") @Suppress("LeakingThis")
@ -114,8 +114,7 @@ public sealed class CustomMessage : SingleMessage {
public override fun load(input: ByteArray): M = json.decodeFromString(serializer(), String(input)) public override fun load(input: ByteArray): M = json.decodeFromString(serializer(), String(input))
} }
public companion object Key : Message.Key<CustomMessage> { public companion object {
override val typeName: String get() = "CustomMessage"
private val factories: LockFreeLinkedList<Factory<*>> = LockFreeLinkedList() private val factories: LockFreeLinkedList<Factory<*>> = LockFreeLinkedList()
internal fun register(factory: Factory<out CustomMessage>) { internal fun register(factory: Factory<out CustomMessage>) {
@ -196,14 +195,12 @@ public fun <T : CustomMessage> T.toByteArray(): ByteArray {
@Serializable @Serializable
@MiraiExperimentalApi @MiraiExperimentalApi
public abstract class CustomMessageMetadata : CustomMessage(), MessageMetadata { public abstract class CustomMessageMetadata : CustomMessage(), MessageMetadata {
public companion object Key : Message.Key<CustomMessageMetadata> {
override val typeName: String get() = "CustomMessageMetadata"
}
public open fun customToString(): ByteArray = customToStringImpl(this.getFactory()) public open fun customToString(): ByteArray = customToStringImpl(this.getFactory())
final override fun toString(): String = final override fun toString(): String =
"[mirai:custom:${getFactory().typeName}:${String(customToString())}]" "[mirai:custom:${getFactory().typeName}:${String(customToString())}]"
public companion object
} }

View File

@ -27,8 +27,7 @@ public data class Face(public val id: Int) : // used in delegation
public override fun toString(): String = "[mirai:face:$id]" public override fun toString(): String = "[mirai:face:$id]"
public override fun contentToString(): String = public override fun contentToString(): String =
if (id >= 0 && id <= 255) if (id in 0..255) FaceName.names[id]
FaceName.names[id]
else "[表情]" else "[表情]"
public override fun equals(other: Any?): Boolean = other is Face && other.id == this.id public override fun equals(other: Any?): Boolean = other is Face && other.id == this.id
@ -38,10 +37,7 @@ public data class Face(public val id: Int) : // used in delegation
* @author LamGC * @author LamGC
*/ */
@Suppress("SpellCheckingInspection", "unused") @Suppress("SpellCheckingInspection", "unused")
public companion object IdList : Message.Key<Face> { public companion object {
public override val typeName: String
get() = "Face"
public const val unknown: Int = 0xff public const val unknown: Int = 0xff
public const val jingya: Int = 0 public const val jingya: Int = 0
public const val piezui: Int = 1 public const val piezui: Int = 1

View File

@ -174,9 +174,7 @@ public data class ForwardMessage(
public val message: Message public val message: Message
} }
public companion object Key : Message.Key<ForwardMessage> { public companion object
public override val typeName: String get() = "ForwardMessage"
}
} }

View File

@ -16,7 +16,6 @@ package net.mamoe.mirai.message.data
import kotlinx.serialization.Contextual import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import net.mamoe.mirai.message.code.CodableMessage import net.mamoe.mirai.message.code.CodableMessage
import net.mamoe.mirai.message.data.PokeMessage.Types
import net.mamoe.mirai.message.data.VipFace.Companion import net.mamoe.mirai.message.data.VipFace.Companion
import net.mamoe.mirai.message.data.VipFace.Kind import net.mamoe.mirai.message.data.VipFace.Kind
@ -28,10 +27,7 @@ import net.mamoe.mirai.message.data.VipFace.Kind
*/ */
@Serializable @Serializable
public sealed class HummerMessage : MessageContent { public sealed class HummerMessage : MessageContent {
public companion object Key : Message.Key<HummerMessage> { public companion object
public override val typeName: String
get() = "HummerMessage"
}
// has service type etc. // has service type etc.
} }
@ -45,7 +41,7 @@ public sealed class HummerMessage : MessageContent {
* ## mirai 码支持 * ## mirai 码支持
* 格式: &#91;mirai:poke:*[name]*,*[type]*,*[id]*&#93; * 格式: &#91;mirai:poke:*[name]*,*[type]*,*[id]*&#93;
* *
* @see Types 使用伴生对象中的常量 * @see PokeMessage.Companion 使用伴生对象中的常量
*/ */
@Serializable @Serializable
public data class PokeMessage internal constructor( public data class PokeMessage internal constructor(
@ -58,10 +54,7 @@ public data class PokeMessage internal constructor(
public val id: Int public val id: Int
) : HummerMessage(), CodableMessage { ) : HummerMessage(), CodableMessage {
@Suppress("DEPRECATION_ERROR", "DEPRECATION", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("DEPRECATION_ERROR", "DEPRECATION", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public companion object Types : Message.Key<PokeMessage> { public companion object {
public override val typeName: String
get() = "PokeMessage"
/** 戳一戳 */ /** 戳一戳 */
@JvmField @JvmField
public val Poke: PokeMessage = PokeMessage("戳一戳", 1, -1) public val Poke: PokeMessage = PokeMessage("戳一戳", 1, -1)
@ -182,9 +175,7 @@ public data class VipFace internal constructor(
} }
@Suppress("DEPRECATION_ERROR", "DEPRECATION", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("DEPRECATION_ERROR", "DEPRECATION", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
public companion object : Message.Key<VipFace> { public companion object {
override val typeName: String get() = "VipFace"
@JvmStatic @JvmStatic
public val LiuLian: Kind = 9 to "榴莲" public val LiuLian: Kind = 9 to "榴莲"
@ -254,8 +245,12 @@ public data class VipFace internal constructor(
* @see Image 查看图片相关信息 * @see Image 查看图片相关信息
*/ */
@Serializable @Serializable
public sealed class FlashImage : MessageContent, HummerMessage(), CodableMessage { public sealed class FlashImage : MessageContent, HummerMessage(), CodableMessage, ConstrainSingle<FlashImage> {
public companion object Key : Message.Key<FlashImage> { override val key: ConstrainSingle.Key<FlashImage> get() = Key
public companion object Key : ConstrainSingle.Key<FlashImage> {
override val typeName: String get() = "FlashImage"
/** /**
* 将普通图片转换为闪照. * 将普通图片转换为闪照.
*/ */
@ -280,9 +275,6 @@ public sealed class FlashImage : MessageContent, HummerMessage(), CodableMessage
public operator fun invoke(imageId: String): FlashImage { public operator fun invoke(imageId: String): FlashImage {
return invoke(Image(imageId)) return invoke(Image(imageId))
} }
public override val typeName: String
get() = "FlashImage"
} }
/** /**
@ -315,7 +307,7 @@ public inline fun FriendImage.flash(): FriendFlashImage = FlashImage(this) as Fr
*/ */
@Serializable @Serializable
public data class GroupFlashImage(@Contextual override val image: GroupImage) : FlashImage() { public data class GroupFlashImage(@Contextual override val image: GroupImage) : FlashImage() {
public companion object Key : Message.Key<GroupFlashImage> { public companion object Key : ConstrainSingle.Key<GroupFlashImage> {
public override val typeName: String get() = "GroupFlashImage" public override val typeName: String get() = "GroupFlashImage"
} }
} }
@ -325,7 +317,7 @@ public data class GroupFlashImage(@Contextual override val image: GroupImage) :
*/ */
@Serializable @Serializable
public data class FriendFlashImage(@Contextual override val image: FriendImage) : FlashImage() { public data class FriendFlashImage(@Contextual override val image: FriendImage) : FlashImage() {
public companion object Key : Message.Key<FriendFlashImage> { public companion object Key : ConstrainSingle.Key<FriendFlashImage> {
public override val typeName: String get() = "FriendFlashImage" public override val typeName: String get() = "FriendFlashImage"
} }
} }

View File

@ -109,9 +109,7 @@ public interface Image : Message, MessageContent, CodableMessage {
} }
} }
public companion object : Message.Key<Image> { public companion object {
override val typeName: String get() = "Image"
/** /**
* 通过 [Image.imageId] 构造一个 [Image] 以便发送. * 通过 [Image.imageId] 构造一个 [Image] 以便发送.
* 这个图片必须是服务器已经存在的图片. * 这个图片必须是服务器已经存在的图片.
@ -189,9 +187,7 @@ public val Image.md5: ByteArray
// NotOnlineImage // NotOnlineImage
public abstract class FriendImage @MiraiInternalApi public constructor() : public abstract class FriendImage @MiraiInternalApi public constructor() :
AbstractImage() { // change to sealed in the future. AbstractImage() { // change to sealed in the future.
public companion object Key : Message.Key<FriendImage> { public companion object
public override val typeName: String get() = "FriendImage"
}
} }
/** /**
@ -203,9 +199,7 @@ public abstract class FriendImage @MiraiInternalApi public constructor() :
// CustomFace // CustomFace
public abstract class GroupImage @MiraiInternalApi public constructor() : public abstract class GroupImage @MiraiInternalApi public constructor() :
AbstractImage() { // change to sealed in the future. AbstractImage() { // change to sealed in the future.
public companion object Key : Message.Key<GroupImage> { public companion object
public override val typeName: String get() = "GroupImage"
}
} }
/** /**

View File

@ -27,9 +27,10 @@ import net.mamoe.mirai.message.MessageEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.MessageSerializer import net.mamoe.mirai.message.MessageSerializer
import net.mamoe.mirai.message.MessageSerializerImpl import net.mamoe.mirai.message.MessageSerializerImpl
import net.mamoe.mirai.message.data.Message.Key import net.mamoe.mirai.message.data.ConstrainSingle.Key
import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiExperimentalApi
import kotlin.contracts.contract import kotlin.contracts.contract
import kotlin.reflect.KClass
/** /**
* 可发送的或从服务器接收的消息. * 可发送的或从服务器接收的消息.
@ -78,23 +79,6 @@ import kotlin.contracts.contract
*/ */
@Serializable(Message.Serializer::class) @Serializable(Message.Serializer::class)
public interface Message { // must be interface. Don't consider any changes. public interface Message { // must be interface. Don't consider any changes.
/**
* 类型 Key. 由伴生对象实现, 表示一个 [Message] 对象的类型.
*
* [MessageChain] , 每个 [Message] 类型都拥有一个`伴生对象`(companion object) 来持有一个 Key
* [MessageChain.get] 时将会使用到这个 Key 进行判断类型.
*
* #### 用例
* [MessageChain.get]: 允许使用数组访问操作符获取指定类型的消息元素 ```val image: Image = chain[Image]```
*
* @param M 指代持有这个 Key 的消息类型
*/
public interface Key<out M : Message> {
/**
* [Key] 指代的 [Message] 类型名. 一般为 `class.simpleName`, "QuoteReply", "PlainText"
*/
public val typeName: String
}
/** /**
* `this` [tail] 连接. * `this` [tail] 连接.
@ -311,12 +295,36 @@ public interface MessageMetadata : SingleMessage {
* *
* 实现此接口的元素将会在连接时自动处理替换. * 实现此接口的元素将会在连接时自动处理替换.
*/ */
public interface ConstrainSingle<out M : Message> : MessageMetadata { public interface ConstrainSingle<out M : Message> : SingleMessage {
/** /**
* 用于判断是否为同一种元素的 [Key] * 用于判断是否为同一种元素的 [Key]
* @see Key 查看更多信息 * @see Key 查看更多信息
*/ */
public val key: Key<M> public val key: Key<M>
/**
* 类型 Key. 由伴生对象实现, 表示一个 [Message] 对象的类型.
*
* [MessageChain] , 每个 [Message] 类型都拥有一个伴生对象 (companion object) 来持有一个 Key
*
* [MessageChain.get] 时将会使用到这个 Key 进行判断类型.
*
* #### 用例
* [MessageChain.get][MessageChain.get]: 允许使用数组访问操作符获取指定类型的消息元素
* ```
* val image: Image = chain[Image]
* ```
*
* @param M 指代持有这个 Key 的消息类型
*/
public interface Key<out M : Message> {
/**
* [Key] 指代的 [Message] 类型名. 一般为 [KClass.simpleName], "QuoteReply", "PlainText"
*
* 仅用于提示作用.
*/
public val typeName: String
}
} }
/** /**

View File

@ -83,7 +83,7 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess {
* @see MessageChain.getOrFail 在找不到此类型的元素时抛出 [NoSuchElementException] * @see MessageChain.getOrFail 在找不到此类型的元素时抛出 [NoSuchElementException]
*/ */
@JvmName("first") @JvmName("first")
public operator fun <M : Message> get(key: Message.Key<M>): M? = firstOrNull(key) public operator fun <M : Message> get(key: ConstrainSingle.Key<M>): M? = firstOrNull(key)
public object Serializer : KSerializer<MessageChain> { public object Serializer : KSerializer<MessageChain> {
private val delegate = ListSerializer(Message.Serializer) private val delegate = ListSerializer(Message.Serializer)
@ -102,8 +102,8 @@ public interface MessageChain : Message, List<SingleMessage>, RandomAccess {
*/ */
@JvmOverloads @JvmOverloads
public inline fun <M : Message> MessageChain.getOrFail( public inline fun <M : Message> MessageChain.getOrFail(
key: Message.Key<M>, key: ConstrainSingle.Key<M>,
crossinline lazyMessage: (key: Message.Key<M>) -> String = { key.typeName } crossinline lazyMessage: (key: ConstrainSingle.Key<M>) -> String = { key.typeName }
): M = firstOrNull(key) ?: throw NoSuchElementException(lazyMessage(key)) ): M = firstOrNull(key) ?: throw NoSuchElementException(lazyMessage(key))
@ -174,7 +174,7 @@ public inline fun <reified M : Message> MessageChain.anyIsInstance(): Boolean =
*/ */
@JvmSynthetic @JvmSynthetic
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
public fun <M : Message> MessageChain.firstOrNull(key: Message.Key<M>): M? = firstOrNullImpl(key) public fun <M : Message> MessageChain.firstOrNull(key: ConstrainSingle.Key<M>): M? = firstOrNullImpl(key)
/** /**
* 获取第一个 [M] 类型的 [Message] 实例 * 获取第一个 [M] 类型的 [Message] 实例
@ -182,7 +182,7 @@ public fun <M : Message> MessageChain.firstOrNull(key: Message.Key<M>): M? = fir
*/ */
@JvmSynthetic @JvmSynthetic
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
public inline fun <M : Message> MessageChain.first(key: Message.Key<M>): M = public inline fun <M : Message> MessageChain.first(key: ConstrainSingle.Key<M>): M =
firstOrNull(key) ?: throw NoSuchElementException("Message type ${key.typeName} not found in chain $this") firstOrNull(key) ?: throw NoSuchElementException("Message type ${key.typeName} not found in chain $this")
/** /**
@ -190,7 +190,7 @@ public inline fun <M : Message> MessageChain.first(key: Message.Key<M>): M =
*/ */
@JvmSynthetic @JvmSynthetic
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
public inline fun <M : Message> MessageChain.any(key: Message.Key<M>): Boolean = firstOrNull(key) != null public inline fun <M : Message> MessageChain.any(key: ConstrainSingle.Key<M>): Boolean = firstOrNull(key) != null
// endregion accessors // endregion accessors

View File

@ -63,7 +63,7 @@ import net.mamoe.mirai.utils.LazyProperty
*/ */
@Serializable(MessageSourceSerializer::class) @Serializable(MessageSourceSerializer::class)
public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSource> { public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSource> {
public final override val key: Message.Key<MessageSource> get() = Key public final override val key: ConstrainSingle.Key<MessageSource> get() = Key
/** /**
* 所属 [Bot.id] * 所属 [Bot.id]
@ -132,7 +132,7 @@ public sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<Me
*/ */
public final override fun toString(): String = "[mirai:source:$ids,$internalIds]" public final override fun toString(): String = "[mirai:source:$ids,$internalIds]"
public companion object Key : Message.Key<MessageSource> { public companion object Key : ConstrainSingle.Key<MessageSource> {
override val typeName: String get() = "MessageSource" override val typeName: String get() = "MessageSource"
/** /**
@ -258,7 +258,7 @@ public inline val MessageSource.botOrNull: Bot?
* @see OnlineMessageSource.toOffline 转为 [OfflineMessageSource] * @see OnlineMessageSource.toOffline 转为 [OfflineMessageSource]
*/ */
public sealed class OnlineMessageSource : MessageSource() { public sealed class OnlineMessageSource : MessageSource() {
public companion object Key : Message.Key<OnlineMessageSource> { public companion object Key : ConstrainSingle.Key<OnlineMessageSource> {
public override val typeName: String get() = "OnlineMessageSource" public override val typeName: String get() = "OnlineMessageSource"
} }
@ -294,7 +294,7 @@ public sealed class OnlineMessageSource : MessageSource() {
* [机器人主动发送消息][Contact.sendMessage] 产生的 [MessageSource], 可通过 [MessageReceipt] 获得. * [机器人主动发送消息][Contact.sendMessage] 产生的 [MessageSource], 可通过 [MessageReceipt] 获得.
*/ */
public sealed class Outgoing : OnlineMessageSource() { public sealed class Outgoing : OnlineMessageSource() {
public companion object Key : Message.Key<Outgoing> { public companion object Key : ConstrainSingle.Key<Outgoing> {
public override val typeName: String get() = "OnlineMessageSource.Outgoing" public override val typeName: String get() = "OnlineMessageSource.Outgoing"
} }
@ -305,7 +305,7 @@ public sealed class OnlineMessageSource : MessageSource() {
public final override val targetId: Long get() = target.id public final override val targetId: Long get() = target.id
public abstract class ToFriend : Outgoing() { public abstract class ToFriend : Outgoing() {
public companion object Key : Message.Key<ToFriend> { public companion object Key : ConstrainSingle.Key<ToFriend> {
public override val typeName: String get() = "OnlineMessageSource.Outgoing.ToFriend" public override val typeName: String get() = "OnlineMessageSource.Outgoing.ToFriend"
} }
@ -315,7 +315,7 @@ public sealed class OnlineMessageSource : MessageSource() {
} }
public abstract class ToTemp : Outgoing() { public abstract class ToTemp : Outgoing() {
public companion object Key : Message.Key<ToTemp> { public companion object Key : ConstrainSingle.Key<ToTemp> {
public override val typeName: String get() = "OnlineMessageSource.Outgoing.ToTemp" public override val typeName: String get() = "OnlineMessageSource.Outgoing.ToTemp"
} }
@ -325,7 +325,7 @@ public sealed class OnlineMessageSource : MessageSource() {
} }
public abstract class ToGroup : Outgoing() { public abstract class ToGroup : Outgoing() {
public companion object Key : Message.Key<ToGroup> { public companion object Key : ConstrainSingle.Key<ToGroup> {
public override val typeName: String get() = "OnlineMessageSource.Outgoing.ToGroup" public override val typeName: String get() = "OnlineMessageSource.Outgoing.ToGroup"
} }
@ -338,7 +338,7 @@ public sealed class OnlineMessageSource : MessageSource() {
* 接收到的一条消息的 [MessageSource] * 接收到的一条消息的 [MessageSource]
*/ */
public sealed class Incoming : OnlineMessageSource() { public sealed class Incoming : OnlineMessageSource() {
public companion object Key : Message.Key<Incoming> { public companion object Key : ConstrainSingle.Key<Incoming> {
public override val typeName: String get() = "OnlineMessageSource.Incoming" public override val typeName: String get() = "OnlineMessageSource.Incoming"
} }
@ -348,7 +348,7 @@ public sealed class OnlineMessageSource : MessageSource() {
public final override val targetId: Long get() = target.id public final override val targetId: Long get() = target.id
public abstract class FromFriend : Incoming() { public abstract class FromFriend : Incoming() {
public companion object Key : Message.Key<FromFriend> { public companion object Key : ConstrainSingle.Key<FromFriend> {
public override val typeName: String get() = "OnlineMessageSource.Incoming.FromFriend" public override val typeName: String get() = "OnlineMessageSource.Incoming.FromFriend"
} }
@ -359,7 +359,7 @@ public sealed class OnlineMessageSource : MessageSource() {
} }
public abstract class FromTemp : Incoming() { public abstract class FromTemp : Incoming() {
public companion object Key : Message.Key<FromTemp> { public companion object Key : ConstrainSingle.Key<FromTemp> {
public override val typeName: String get() = "OnlineMessageSource.Incoming.FromTemp" public override val typeName: String get() = "OnlineMessageSource.Incoming.FromTemp"
} }
@ -370,7 +370,7 @@ public sealed class OnlineMessageSource : MessageSource() {
} }
public abstract class FromGroup : Incoming() { public abstract class FromGroup : Incoming() {
public companion object Key : Message.Key<FromGroup> { public companion object Key : ConstrainSingle.Key<FromGroup> {
public override val typeName: String get() = "OnlineMessageSource.Incoming.FromGroup" public override val typeName: String get() = "OnlineMessageSource.Incoming.FromGroup"
} }
@ -389,7 +389,7 @@ public sealed class OnlineMessageSource : MessageSource() {
* @see buildMessageSource 构建一个 [OfflineMessageSource] * @see buildMessageSource 构建一个 [OfflineMessageSource]
*/ */
public abstract class OfflineMessageSource : MessageSource() { public abstract class OfflineMessageSource : MessageSource() {
public companion object Key : Message.Key<OfflineMessageSource> { public companion object Key : ConstrainSingle.Key<OfflineMessageSource> {
public override val typeName: String get() = "OfflineMessageSource" public override val typeName: String get() = "OfflineMessageSource"
} }

View File

@ -30,9 +30,7 @@ public data class PlainText(
public override fun toString(): String = content public override fun toString(): String = content
public override fun contentToString(): String = content public override fun contentToString(): String = content
public companion object Key : Message.Key<PlainText> { public companion object
public override val typeName: String get() = "PlainText"
}
} }
/** /**

View File

@ -40,12 +40,12 @@ import net.mamoe.mirai.message.data.MessageSource.Key.recall
*/ */
@Serializable @Serializable
public data class QuoteReply(public val source: MessageSource) : Message, MessageMetadata, ConstrainSingle<QuoteReply> { public data class QuoteReply(public val source: MessageSource) : Message, MessageMetadata, ConstrainSingle<QuoteReply> {
public companion object Key : Message.Key<QuoteReply> { public companion object Key : ConstrainSingle.Key<QuoteReply> {
public override val typeName: String public override val typeName: String
get() = "QuoteReply" get() = "QuoteReply"
} }
public override val key: Message.Key<QuoteReply> get() = Key public override val key: ConstrainSingle.Key<QuoteReply> get() = Key
// TODO: 2020/12/2 QuoteReply.toString // TODO: 2020/12/2 QuoteReply.toString
public override fun toString(): String = "[mirai:quote:${source.ids},${source.internalIds}]" public override fun toString(): String = "[mirai:quote:${source.ids},${source.internalIds}]"

View File

@ -45,7 +45,7 @@ public interface RichMessage : MessageContent {
* @suppress API 不稳定, 可能在任意时刻被删除 * @suppress API 不稳定, 可能在任意时刻被删除
*/ */
@MiraiExperimentalApi @MiraiExperimentalApi
public companion object Templates : Message.Key<RichMessage> { public companion object Templates : ConstrainSingle.Key<RichMessage> {
/** /**
* @suppress API 不稳定, 可能在任意时刻被删除 * @suppress API 不稳定, 可能在任意时刻被删除
@ -93,7 +93,7 @@ public interface RichMessage : MessageContent {
*/ */
@Serializable @Serializable
public data class LightApp(override val content: String) : RichMessage { public data class LightApp(override val content: String) : RichMessage {
public companion object Key : Message.Key<LightApp> { public companion object Key : ConstrainSingle.Key<LightApp> {
public override val typeName: String get() = "LightApp" public override val typeName: String get() = "LightApp"
} }
@ -116,7 +116,7 @@ public class SimpleServiceMessage(
public override val serviceId: Int, public override val serviceId: Int,
public override val content: String public override val content: String
) : ServiceMessage { ) : ServiceMessage {
public companion object Key : Message.Key<ServiceMessage> { public companion object Key : ConstrainSingle.Key<ServiceMessage> {
public override val typeName: String get() = "ServiceMessage" public override val typeName: String get() = "ServiceMessage"
} }
@ -146,7 +146,7 @@ public class SimpleServiceMessage(
* @see SimpleServiceMessage * @see SimpleServiceMessage
*/ */
public interface ServiceMessage : RichMessage { public interface ServiceMessage : RichMessage {
public companion object Key : Message.Key<ServiceMessage> { public companion object Key : ConstrainSingle.Key<ServiceMessage> {
public override val typeName: String get() = "ServiceMessage" public override val typeName: String get() = "ServiceMessage"
} }
@ -258,7 +258,7 @@ internal class LongMessage internal constructor(override val content: String, va
AbstractServiceMessage() { AbstractServiceMessage() {
override val serviceId: Int get() = 35 override val serviceId: Int get() = 35
companion object Key : Message.Key<LongMessage> { companion object Key : ConstrainSingle.Key<LongMessage> {
override val typeName: String get() = "LongMessage" override val typeName: String get() = "LongMessage"
} }
} }

View File

@ -21,7 +21,7 @@ import net.mamoe.mirai.utils.MiraiInternalApi
@MiraiExperimentalApi @MiraiExperimentalApi
public abstract class PttMessage : MessageContent { public abstract class PttMessage : MessageContent {
public companion object Key : Message.Key<PttMessage> { public companion object Key : ConstrainSingle.Key<PttMessage> {
public override val typeName: String public override val typeName: String
get() = "PttMessage" get() = "PttMessage"
} }
@ -43,7 +43,7 @@ public class Voice @MiraiInternalApi constructor(
private val _url: String private val _url: String
) : PttMessage() { ) : PttMessage() {
public companion object Key : Message.Key<Voice> { public companion object Key : ConstrainSingle.Key<Voice> {
override val typeName: String override val typeName: String
get() = "Voice" get() = "Voice"
} }

View File

@ -14,9 +14,6 @@
package net.mamoe.mirai.message.data package net.mamoe.mirai.message.data
import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiExperimentalApi
import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.native.concurrent.SharedImmutable import kotlin.native.concurrent.SharedImmutable
// region image // region image
@ -25,7 +22,7 @@ import kotlin.native.concurrent.SharedImmutable
//// IMPLEMENTATIONS //// //// IMPLEMENTATIONS ////
///////////////////////// /////////////////////////
private fun Message.hasDuplicationOfConstrain(key: Message.Key<*>): Boolean { private fun Message.hasDuplicationOfConstrain(key: ConstrainSingle.Key<*>): Boolean {
return when (this) { return when (this) {
is SingleMessage -> (this as? ConstrainSingle<*>)?.key == key is SingleMessage -> (this as? ConstrainSingle<*>)?.key == key
is CombinedMessage -> return this.left.hasDuplicationOfConstrain(key) || this.tail.hasDuplicationOfConstrain(key) is CombinedMessage -> return this.left.hasDuplicationOfConstrain(key) || this.tail.hasDuplicationOfConstrain(key)
@ -191,16 +188,9 @@ internal inline fun <T> List<T>.indexOfFirst(offset: Int, predicate: (T) -> Bool
@JvmSynthetic @JvmSynthetic
@Suppress("UNCHECKED_CAST", "DEPRECATION_ERROR", "DEPRECATION") @Suppress("UNCHECKED_CAST", "DEPRECATION_ERROR", "DEPRECATION")
internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M? = when (key) { internal fun <M : Message> MessageChain.firstOrNullImpl(key: ConstrainSingle.Key<M>): M? = when (key) {
At -> firstIsInstanceOrNull<At>()
AtAll -> firstIsInstanceOrNull<AtAll>()
PlainText -> firstIsInstanceOrNull<PlainText>()
Image -> firstIsInstanceOrNull<Image>()
// OnlineImage -> firstIsInstanceOrNull<OnlineImage>() // OnlineImage -> firstIsInstanceOrNull<OnlineImage>()
// OfflineImage -> firstIsInstanceOrNull<OfflineImage>() // OfflineImage -> firstIsInstanceOrNull<OfflineImage>()
GroupImage -> firstIsInstanceOrNull<GroupImage>()
FriendImage -> firstIsInstanceOrNull<FriendImage>()
Face -> firstIsInstanceOrNull<Face>()
QuoteReply -> firstIsInstanceOrNull<QuoteReply>() QuoteReply -> firstIsInstanceOrNull<QuoteReply>()
MessageSource -> firstIsInstanceOrNull<MessageSource>() MessageSource -> firstIsInstanceOrNull<MessageSource>()
OnlineMessageSource -> firstIsInstanceOrNull<OnlineMessageSource>() OnlineMessageSource -> firstIsInstanceOrNull<OnlineMessageSource>()
@ -215,14 +205,9 @@ internal fun <M : Message> MessageChain.firstOrNullImpl(key: Message.Key<M>): M?
LongMessage -> firstIsInstanceOrNull() LongMessage -> firstIsInstanceOrNull()
RichMessage -> firstIsInstanceOrNull<RichMessage>() RichMessage -> firstIsInstanceOrNull<RichMessage>()
LightApp -> firstIsInstanceOrNull<LightApp>() LightApp -> firstIsInstanceOrNull<LightApp>()
PokeMessage -> firstIsInstanceOrNull<PokeMessage>()
HummerMessage -> firstIsInstanceOrNull<HummerMessage>()
FlashImage -> firstIsInstanceOrNull<FlashImage>() FlashImage -> firstIsInstanceOrNull<FlashImage>()
GroupFlashImage -> firstIsInstanceOrNull<GroupFlashImage>() GroupFlashImage -> firstIsInstanceOrNull<GroupFlashImage>()
FriendFlashImage -> firstIsInstanceOrNull<FriendFlashImage>() FriendFlashImage -> firstIsInstanceOrNull<FriendFlashImage>()
CustomMessage -> firstIsInstanceOrNull()
CustomMessageMetadata -> firstIsInstanceOrNull()
ForwardMessage -> firstIsInstanceOrNull()
PttMessage -> firstIsInstanceOrNull<PttMessage>() PttMessage -> firstIsInstanceOrNull<PttMessage>()
Voice -> firstIsInstanceOrNull<Voice>() Voice -> firstIsInstanceOrNull<Voice>()
else -> { else -> {

View File

@ -15,14 +15,15 @@ import kotlin.test.assertTrue
internal class TestConstrainSingleMessage : ConstrainSingle<TestConstrainSingleMessage>, Any() { internal class TestConstrainSingleMessage : ConstrainSingle<TestConstrainSingleMessage>, Any() {
companion object Key : Message.Key<TestConstrainSingleMessage> { companion object Key : ConstrainSingle.Key<TestConstrainSingleMessage> {
override val typeName: String override val typeName: String
get() = "TestMessage" get() = "TestMessage"
} }
override fun toString(): String = "<TestConstrainSingleMessage#${super.hashCode()}>" override fun toString(): String = "<TestConstrainSingleMessage#${super.hashCode()}>"
override fun contentToString(): String = ""
override val key: Message.Key<TestConstrainSingleMessage> override val key: ConstrainSingle.Key<TestConstrainSingleMessage>
get() = Key get() = Key
} }

View File

@ -436,14 +436,14 @@ internal fun List<ImMsgBody.Elem>.joinToMessageChain(groupIdOrZero: Long, botId:
CustomMessage.load(this) CustomMessage.load(this)
}.fold( }.fold(
onFailure = { onFailure = {
if (it is CustomMessage.Key.CustomMessageFullDataDeserializeInternalException) { if (it is CustomMessage.Companion.CustomMessageFullDataDeserializeInternalException) {
throw IllegalStateException( throw IllegalStateException(
"Internal error: " + "Internal error: " +
"exception while deserializing CustomMessage head data," + "exception while deserializing CustomMessage head data," +
" data=${element.customElem.data.toUHexString()}", it " data=${element.customElem.data.toUHexString()}", it
) )
} else { } else {
it as CustomMessage.Key.CustomMessageFullDataDeserializeUserException it as CustomMessage.Companion.CustomMessageFullDataDeserializeUserException
throw IllegalStateException( throw IllegalStateException(
"User error: " + "User error: " +
"exception while deserializing CustomMessage body," + "exception while deserializing CustomMessage body," +

View File

@ -146,7 +146,7 @@ internal val firstOnlineBotInstance: Bot get() = Bot.botInstancesSequence.firstO
@Suppress("EXPOSED_SUPER_INTERFACE") @Suppress("EXPOSED_SUPER_INTERFACE")
internal interface OnlineImage : Image, ConstOriginUrlAware { internal interface OnlineImage : Image, ConstOriginUrlAware {
companion object Key : Message.Key<OnlineImage> { companion object Key : ConstrainSingle.Key<OnlineImage> {
override val typeName: String get() = "OnlineImage" override val typeName: String get() = "OnlineImage"
} }
@ -160,7 +160,7 @@ internal interface OnlineImage : Image, ConstOriginUrlAware {
* 一般由 [Contact.uploadImage] 得到 * 一般由 [Contact.uploadImage] 得到
*/ */
internal interface OfflineImage : Image { internal interface OfflineImage : Image {
companion object Key : Message.Key<OfflineImage> { companion object Key : ConstrainSingle.Key<OfflineImage> {
override val typeName: String get() = "OfflineImage" override val typeName: String get() = "OfflineImage"
} }
} }

View File

@ -11,21 +11,21 @@ package net.mamoe.mirai.internal
import net.mamoe.mirai.message.data.ConstrainSingle import net.mamoe.mirai.message.data.ConstrainSingle
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.message.data.buildMessageChain import net.mamoe.mirai.message.data.buildMessageChain
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertFalse import kotlin.test.assertFalse
import kotlin.test.assertTrue import kotlin.test.assertTrue
internal class TestConstrainSingleMessage : ConstrainSingle<TestConstrainSingleMessage>, Any() { internal class TestConstrainSingleMessage : ConstrainSingle<TestConstrainSingleMessage>, Any() {
companion object Key : Message.Key<TestConstrainSingleMessage> { companion object Key : ConstrainSingle.Key<TestConstrainSingleMessage> {
override val typeName: String override val typeName: String
get() = "TestMessage" get() = "TestMessage"
} }
override fun toString(): String = "<TestConstrainSingleMessage#${super.hashCode()}>" override fun toString(): String = "<TestConstrainSingleMessage#${super.hashCode()}>"
override fun contentToString(): String = ""
override val key: Message.Key<TestConstrainSingleMessage> override val key: ConstrainSingle.Key<TestConstrainSingleMessage>
get() = Key get() = Key
} }