Make Message.get returns M? instead of M;

Deprecate `Message.getOrNull` in favor of `Message.get`;
Add `Message.getOrFail`
This commit is contained in:
Him188 2020-05-06 12:38:30 +08:00
parent 3255e330c0
commit 5cd3178c3f
7 changed files with 41 additions and 32 deletions

View File

@ -38,10 +38,10 @@ private val UNSUPPORTED_FLASH_MESSAGE_PLAIN = PlainText("[闪照]请使用新版
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class) @OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: Boolean): MutableList<ImMsgBody.Elem> { internal fun MessageChain.toRichTextElems(forGroup: Boolean, withGeneralFlags: Boolean): MutableList<ImMsgBody.Elem> {
val elements = mutableListOf<ImMsgBody.Elem>() val elements = ArrayList<ImMsgBody.Elem>(this.size)
if (this.anyIsInstance<QuoteReply>()) { if (this.anyIsInstance<QuoteReply>()) {
when (val source = this[QuoteReply].source) { when (val source = this[QuoteReply]!!.source) {
is MessageSourceInternal -> elements.add(ImMsgBody.Elem(srcMsg = source.toJceData())) is MessageSourceInternal -> elements.add(ImMsgBody.Elem(srcMsg = source.toJceData()))
else -> error("unsupported MessageSource implementation: ${source::class.simpleName}. Don't implement your own MessageSource.") else -> error("unsupported MessageSource implementation: ${source::class.simpleName}. Don't implement your own MessageSource.")
} }

View File

@ -32,7 +32,7 @@ class FriendMessageEvent constructor(
) : @PlannedRemoval("1.2.0") FriendMessage(), BroadcastControllable { ) : @PlannedRemoval("1.2.0") FriendMessage(), BroadcastControllable {
init { init {
val source = val source =
message.getOrNull(MessageSource) ?: throw IllegalArgumentException("Cannot find MessageSource from message") message[MessageSource] ?: throw IllegalArgumentException("Cannot find MessageSource from message")
check(source is OnlineMessageSource.Incoming.FromFriend) { "source provided to a FriendMessage must be an instance of OnlineMessageSource.Incoming.FromFriend" } check(source is OnlineMessageSource.Incoming.FromFriend) { "source provided to a FriendMessage must be an instance of OnlineMessageSource.Incoming.FromFriend" }
} }

View File

@ -35,7 +35,7 @@ class GroupMessageEvent(
override val time: Int override val time: Int
) : @PlannedRemoval("1.2.0") GroupMessage(), Event { ) : @PlannedRemoval("1.2.0") GroupMessage(), Event {
init { init {
val source = message.getOrNull(MessageSource) ?: error("Cannot find MessageSource from message") val source = message[MessageSource] ?: error("Cannot find MessageSource from message")
check(source is OnlineMessageSource.Incoming.FromGroup) { "source provided to a GroupMessage must be an instance of OnlineMessageSource.Incoming.FromGroup" } check(source is OnlineMessageSource.Incoming.FromGroup) { "source provided to a GroupMessage must be an instance of OnlineMessageSource.Incoming.FromGroup" }
} }

View File

@ -135,11 +135,6 @@ interface MessageEventExtensions<out TSender : User, out TSubject : Contact> :
@JvmSynthetic @JvmSynthetic
suspend inline fun quoteReply(plain: String): MessageReceipt<TSubject> = reply(this.message.quote() + plain) suspend inline fun quoteReply(plain: String): MessageReceipt<TSubject> = reply(this.message.quote() + plain)
@JvmSynthetic
inline operator fun <M : Message> get(at: Message.Key<M>): M {
return this.message[at]
}
@JvmSynthetic @JvmSynthetic
inline fun At.isBot(): Boolean = target == bot.id inline fun At.isBot(): Boolean = target == bot.id

View File

@ -23,7 +23,7 @@ class TempMessageEvent(
override val time: Int override val time: Int
) : TempMessage(), BroadcastControllable { ) : TempMessage(), BroadcastControllable {
init { init {
val source = message.getOrNull(MessageSource) ?: error("Cannot find MessageSource from message") val source = message[MessageSource] ?: error("Cannot find MessageSource from message")
check(source is OnlineMessageSource.Incoming.FromTemp) { "source provided to a TempMessage must be an instance of OnlineMessageSource.Incoming.FromTemp" } check(source is OnlineMessageSource.Incoming.FromTemp) { "source provided to a TempMessage must be an instance of OnlineMessageSource.Incoming.FromTemp" }
} }

View File

@ -20,6 +20,7 @@ import net.mamoe.mirai.utils.MiraiInternalAPI
import kotlin.js.JsName import kotlin.js.JsName
import kotlin.jvm.JvmMultifileClass import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.jvm.JvmOverloads
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
@ -46,23 +47,13 @@ interface MessageChain : Message, Iterable<SingleMessage> {
val size: Int val size: Int
/** /**
* 获取第一个类型为 [key] [Message] 实例 * 获取第一个类型为 [key] [Message] 实例. 若不存在此实例, 返回 `null`
* *
* @param key 由各个类型消息的伴生对象持有. [PlainText.Key] * @param key 由各个类型消息的伴生对象持有. [PlainText.Key]
* @throws NoSuchElementException 当找不到这个类型的 [Message]
*/ */
@Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION", "INAPPLICABLE_JVM_NAME") @Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION", "INAPPLICABLE_JVM_NAME")
@JvmName("first") @JvmName("first")
final operator fun <M : Message> get(key: Message.Key<M>): M = first(key) final operator fun <M : Message> get(key: Message.Key<M>): M? = firstOrNull(key)
/**
* 获取第一个类型为 [key] [Message] 实例, 找不到则返回 `null`
*
* @param key 由各个类型消息的伴生对象持有. [PlainText.Key]
*/
@Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION", "INAPPLICABLE_JVM_NAME")
@JvmName("firstOrNull")
final fun <M : Message> getOrNull(key: Message.Key<M>): M? = firstOrNull(key)
/** /**
* 遍历每一个有内容的消息, [At], [AtAll], [PlainText], [Image], [Face] * 遍历每一个有内容的消息, [At], [AtAll], [PlainText], [Image], [Face]
@ -87,10 +78,33 @@ interface MessageChain : Message, Iterable<SingleMessage> {
final fun __forEachForJava__(block: (Message) -> Unit) { final fun __forEachForJava__(block: (Message) -> Unit) {
this.forEach(block) this.forEach(block)
} }
/**
* 获取第一个类型为 [key] [Message] 实例, 找不到则返回 `null`
*
* @param key 由各个类型消息的伴生对象持有. [PlainText.Key]
*/
@Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION", "INAPPLICABLE_JVM_NAME")
@JvmName("firstOrNull")
@Deprecated("use get", ReplaceWith("get(key)"))
final fun <M : Message> getOrNull(key: Message.Key<M>): M? = get(key)
} }
// region accessors // region accessors
/**
* 获取第一个类型为 [key] [Message] 实例
*
* @param key 由各个类型消息的伴生对象持有. [PlainText.Key]
*/
@JvmOverloads
inline fun <M : Message> MessageChain.getOrFail(
key: Message.Key<M>,
crossinline lazyMessage: (key: Message.Key<M>) -> String = { key.typeName }
): M = firstOrNull(key) ?: throw NoSuchElementException(lazyMessage(key))
/** /**
* 遍历每一个 [消息内容][MessageContent] * 遍历每一个 [消息内容][MessageContent]
*/ */

View File

@ -109,17 +109,17 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
* 发送人. * 发送人.
* *
* - [OnlineMessageSource.Outgoing] 时为 [机器人][Bot.id] * - [OnlineMessageSource.Outgoing] 时为 [机器人][Bot.id]
* - [OnlineMessageSource.Incoming] 时为发信 [目标好友][QQ.id] [][Group.id] * - [OnlineMessageSource.Incoming] 时为发信 [目标好友][Friend.id] [][Group.id]
* - [OfflineMessageSource] 时为 [机器人][Bot.id], 发信 [目标好友][QQ.id] [][Group.id] (取决于 [OfflineMessageSource.kind]) * - [OfflineMessageSource] 时为 [机器人][Bot.id], 发信 [目标好友][Friend.id] [][Group.id] (取决于 [OfflineMessageSource.kind])
*/ */
abstract val fromId: Long abstract val fromId: Long
/** /**
* 消息发送目标. * 消息发送目标.
* *
* - [OnlineMessageSource.Outgoing] 时为发信 [目标好友][QQ.id] [][Group.id] [临时消息][Member.id] * - [OnlineMessageSource.Outgoing] 时为发信 [目标好友][Friend.id] [][Group.id] [临时消息][Member.id]
* - [OnlineMessageSource.Incoming] 时为 [机器人][Bot.id] * - [OnlineMessageSource.Incoming] 时为 [机器人][Bot.id]
* - [OfflineMessageSource] 时为 [机器人][Bot.id], 发信 [目标好友][QQ.id] [][Group.id] [临时消息][Member.id] (取决于 [OfflineMessageSource.kind]) * - [OfflineMessageSource] 时为 [机器人][Bot.id], 发信 [目标好友][Friend.id] [][Group.id] [临时消息][Member.id] (取决于 [OfflineMessageSource.kind])
*/ */
abstract val targetId: Long // groupCode / friendUin / memberUin abstract val targetId: Long // groupCode / friendUin / memberUin
@ -171,19 +171,19 @@ sealed class OnlineMessageSource : MessageSource() {
} }
/** /**
* 消息发送人. 可能为 [机器人][Bot] [好友][QQ] [群员][Member]. * 消息发送人. 可能为 [机器人][Bot] [好友][Friend] [群员][Member].
* 即类型必定为 [Bot], [QQ] [Member] * 即类型必定为 [Bot], [Friend] [Member]
*/ */
abstract val sender: ContactOrBot abstract val sender: ContactOrBot
/** /**
* 消息发送目标. 可能为 [机器人][Bot] [好友][QQ] [][Group]. * 消息发送目标. 可能为 [机器人][Bot] [好友][Friend] [][Group].
* 即类型必定为 [Bot], [QQ] [Group] * 即类型必定为 [Bot], [Friend] [Group]
*/ */
abstract val target: ContactOrBot abstract val target: ContactOrBot
/** /**
* 消息主体. 群消息时为 [Group]. 好友消息时为 [QQ], 临时消息为 [Member] * 消息主体. 群消息时为 [Group]. 好友消息时为 [Friend], 临时消息为 [Member]
* 不论是机器人接收的消息还是发送的消息, 此属性都指向机器人能进行回复的目标. * 不论是机器人接收的消息还是发送的消息, 此属性都指向机器人能进行回复的目标.
*/ */
abstract val subject: Contact abstract val subject: Contact
@ -436,7 +436,7 @@ inline val MessageChain.bot: Bot
*/ */
@get:JvmSynthetic @get:JvmSynthetic
inline val MessageChain.source: MessageSource inline val MessageChain.source: MessageSource
get() = this[MessageSource] get() = this.getOrFail(MessageSource)
/** /**
* 撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息. * 撤回这条消息. 可撤回自己 2 分钟内发出的消息, 和任意时间的群成员的消息.