Plan for redesigning of MessageSource

This commit is contained in:
Him188 2020-03-29 13:34:54 +08:00
parent 6d5b3086f6
commit b6c24e008d
19 changed files with 90 additions and 15 deletions

View File

@ -163,6 +163,7 @@ internal abstract class QQAndroidBotBase constructor(
TODO("not implemented") TODO("not implemented")
} }
@ExperimentalMessageSource
override suspend fun recall(source: MessageSource) { override suspend fun recall(source: MessageSource) {
if (source.senderId != uin && source.groupId != 0L) { if (source.senderId != uin && source.groupId != 0L) {
getGroup(source.groupId).checkBotPermissionOperator() getGroup(source.groupId).checkBotPermissionOperator()
@ -382,8 +383,9 @@ internal abstract class QQAndroidBotBase constructor(
val data = chain.calculateValidationDataForGroup( val data = chain.calculateValidationDataForGroup(
sequenceId = client.atomicNextMessageSequenceId(), sequenceId = client.atomicNextMessageSequenceId(),
time = time.toInt(), time = time.toInt(),
random = Random.nextInt().absoluteValue.toULong().toLong(), random = Random.nextInt().absoluteValue.toUInt(),
group groupCode,
group.botAsMember.nameCardOrNick
) )
val response = val response =

View File

@ -278,7 +278,7 @@ internal class GroupImpl(
check(!isBotMuted) { "bot is muted. Remaining seconds=$botMuteRemaining" } check(!isBotMuted) { "bot is muted. Remaining seconds=$botMuteRemaining" }
val event = GroupMessageSendEvent(this, message.asMessageChain()).broadcast() val event = GroupMessageSendEvent(this, message.asMessageChain()).broadcast()
if (event.isCancelled) { if (event.isCancelled) {
throw EventCancelledException("cancelled by FriendMessageSendEvent") throw EventCancelledException("cancelled by GroupMessageSendEvent")
} }
lateinit var source: MessageSourceFromSendGroup lateinit var source: MessageSourceFromSendGroup
bot.network.run { bot.network.run {

View File

@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.qqandroid.contact package net.mamoe.mirai.qqandroid.contact
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

View File

@ -8,6 +8,7 @@
*/ */
@file:OptIn(MiraiInternalAPI::class, LowLevelAPI::class) @file:OptIn(MiraiInternalAPI::class, LowLevelAPI::class)
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.qqandroid.contact package net.mamoe.mirai.qqandroid.contact

View File

@ -7,6 +7,8 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file:Suppress("EXPERIMENTAL_API_USAGE", "EXPERIMENTAL_OVERRIDE")
package net.mamoe.mirai.qqandroid.message package net.mamoe.mirai.qqandroid.message
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
@ -146,7 +148,7 @@ internal abstract class MessageSourceFromSend : MessageSource {
} }
private val elems by lazy { private val elems by lazy {
originalMessage.toRichTextElems(groupId != 0L) originalMessage.toRichTextElems(groupId != 0L, true)
} }
private fun toJceDataImplForFriend(): ImMsgBody.SourceMsg { private fun toJceDataImplForFriend(): ImMsgBody.SourceMsg {

View File

@ -7,6 +7,7 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * https://github.com/mamoe/mirai/blob/master/LICENSE
*/ */
@file: OptIn(MiraiExperimentalAPI::class, MiraiInternalAPI::class, LowLevelAPI::class, ExperimentalUnsignedTypes::class) @file: OptIn(MiraiExperimentalAPI::class, MiraiInternalAPI::class, LowLevelAPI::class, ExperimentalUnsignedTypes::class)
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.qqandroid.message package net.mamoe.mirai.qqandroid.message

View File

@ -52,7 +52,7 @@ internal fun MessageChain.calculateValidationDataForGroup(
groupCode: Long, groupCode: Long,
botMemberNameCard: String botMemberNameCard: String
): MessageValidationData { ): MessageValidationData {
val richTextElems = this.toRichTextElems(true) val richTextElems = this.toRichTextElems(true, false)
val msgTransmit = MsgTransmit.PbMultiMsgTransmit( val msgTransmit = MsgTransmit.PbMultiMsgTransmit(
msg = listOf( msg = listOf(

View File

@ -319,7 +319,7 @@ internal class MessageSvc {
contentHead = MsgComm.ContentHead(pkgNum = 1), contentHead = MsgComm.ContentHead(pkgNum = 1),
msgBody = ImMsgBody.MsgBody( msgBody = ImMsgBody.MsgBody(
richText = ImMsgBody.RichText( richText = ImMsgBody.RichText(
elems = message.toRichTextElems(false) elems = message.toRichTextElems(false, true)
) )
), ),
msgSeq = source.sequenceId, msgSeq = source.sequenceId,
@ -372,7 +372,7 @@ internal class MessageSvc {
contentHead = MsgComm.ContentHead(pkgNum = 1), contentHead = MsgComm.ContentHead(pkgNum = 1),
msgBody = ImMsgBody.MsgBody( msgBody = ImMsgBody.MsgBody(
richText = ImMsgBody.RichText( richText = ImMsgBody.RichText(
elems = message.toRichTextElems(true) elems = message.toRichTextElems(true, true)
) )
), ),
msgSeq = client.atomicNextMessageSequenceId(), msgSeq = client.atomicNextMessageSequenceId(),

View File

@ -7,6 +7,7 @@ import kotlinx.coroutines.io.ByteReadChannel
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.ExperimentalMessageSource
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.message.data.MessageSource
@ -152,6 +153,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA
* @see _lowLevelRecallFriendMessage 低级 API * @see _lowLevelRecallFriendMessage 低级 API
* @see _lowLevelRecallGroupMessage 低级 API * @see _lowLevelRecallGroupMessage 低级 API
*/ */
@ExperimentalMessageSource
@JvmSynthetic @JvmSynthetic
actual abstract suspend fun recall(source: MessageSource) actual abstract suspend fun recall(source: MessageSource)

View File

@ -5,6 +5,7 @@ import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.contact.recall import net.mamoe.mirai.contact.recall
import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.ExperimentalMessageSource
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.message.data.MessageSource
@ -61,6 +62,7 @@ actual abstract class BotJavaFriendlyAPI actual constructor() {
* *
* @see Bot.recall (扩展函数) 接受参数 [MessageChain] * @see Bot.recall (扩展函数) 接受参数 [MessageChain]
*/ */
@ExperimentalMessageSource
@JvmName("recall") @JvmName("recall")
fun __recallBlockingForJava__(source: MessageSource) { fun __recallBlockingForJava__(source: MessageSource) {
runBlocking { recall(source) } runBlocking { recall(source) }
@ -88,6 +90,7 @@ actual abstract class BotJavaFriendlyAPI actual constructor() {
* @param millis 延迟的时间, 单位为毫秒 * @param millis 延迟的时间, 单位为毫秒
* @see recall * @see recall
*/ */
@ExperimentalMessageSource
@JvmName("recallIn") @JvmName("recallIn")
fun __recallIn_MemberForJava__(source: MessageSource, millis: Long) { fun __recallIn_MemberForJava__(source: MessageSource, millis: Long) {
runBlocking { recallIn(source, millis) } runBlocking { recallIn(source, millis) }
@ -148,6 +151,7 @@ actual abstract class BotJavaFriendlyAPI actual constructor() {
/** /**
* 异步调用 [__recallBlockingForJava__] * 异步调用 [__recallBlockingForJava__]
*/ */
@ExperimentalMessageSource
@JvmName("recallAsync") @JvmName("recallAsync")
fun __recallAsyncForJava__(source: MessageSource): Future<Unit> { fun __recallAsyncForJava__(source: MessageSource): Future<Unit> {
return future { recall(source) } return future { recall(source) }

View File

@ -29,7 +29,8 @@ import net.mamoe.mirai.utils.unsafeWeakRef
*/ */
@Suppress("FunctionName") @Suppress("FunctionName")
@OptIn(MiraiInternalAPI::class) @OptIn(MiraiInternalAPI::class)
actual open class MessageReceipt<C : Contact> actual constructor( actual open class MessageReceipt<C : Contact> @OptIn(ExperimentalMessageSource::class)
actual constructor(
actual val source: MessageSource, actual val source: MessageSource,
target: C, target: C,
private val botAsMember: Member? private val botAsMember: Member?
@ -56,6 +57,7 @@ actual open class MessageReceipt<C : Contact> actual constructor(
* @see Bot.recall * @see Bot.recall
* @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时
*/ */
@OptIn(ExperimentalMessageSource::class)
actual suspend fun recall() { actual suspend fun recall() {
@Suppress("BooleanLiteralArgument") @Suppress("BooleanLiteralArgument")
if (_isRecalled.compareAndSet(false, true)) { if (_isRecalled.compareAndSet(false, true)) {
@ -82,7 +84,8 @@ actual open class MessageReceipt<C : Contact> actual constructor(
if (_isRecalled.compareAndSet(false, true)) { if (_isRecalled.compareAndSet(false, true)) {
return when (val contact = target) { return when (val contact = target) {
is QQ, is QQ,
is Group -> contact.bot.recallIn(source, millis) is Group,
-> contact.bot.recallIn(source, millis)
else -> error("Unknown contact type") else -> error("Unknown contact type")
} }
} else error("message is already or planned to be recalled") } else error("message is already or planned to be recalled")
@ -92,6 +95,7 @@ actual open class MessageReceipt<C : Contact> actual constructor(
* [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息. * [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息.
* @see MessageChain.quote 引用一条消息 * @see MessageChain.quote 引用一条消息
*/ */
@OptIn(ExperimentalMessageSource::class)
actual open suspend fun quote(): QuoteReplyToSend { actual open suspend fun quote(): QuoteReplyToSend {
this.source.ensureSequenceIdAvailable() this.source.ensureSequenceIdAvailable()
@OptIn(LowLevelAPI::class) @OptIn(LowLevelAPI::class)
@ -105,6 +109,7 @@ actual open class MessageReceipt<C : Contact> actual constructor(
* *
* @see MessageChain.quote 引用一条消息 * @see MessageChain.quote 引用一条消息
*/ */
@OptIn(ExperimentalMessageSource::class)
@LowLevelAPI @LowLevelAPI
@Suppress("FunctionName") @Suppress("FunctionName")
actual fun _unsafeQuote(): QuoteReplyToSend { actual fun _unsafeQuote(): QuoteReplyToSend {

View File

@ -19,6 +19,7 @@ import kotlinx.coroutines.launch
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.ExperimentalMessageSource
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.message.data.MessageSource
@ -33,6 +34,7 @@ import kotlin.jvm.JvmSynthetic
/** /**
* 登录, 返回 [this] * 登录, 返回 [this]
*/ */
@JvmSynthetic
suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() } suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() }
// 任何人都能看到这个方法 // 任何人都能看到这个方法
@ -167,6 +169,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor {
* @see _lowLevelRecallFriendMessage 低级 API * @see _lowLevelRecallFriendMessage 低级 API
* @see _lowLevelRecallGroupMessage 低级 API * @see _lowLevelRecallGroupMessage 低级 API
*/ */
@ExperimentalMessageSource
@JvmSynthetic @JvmSynthetic
abstract suspend fun recall(source: MessageSource) abstract suspend fun recall(source: MessageSource)
@ -223,6 +226,7 @@ expect abstract class Bot() : CoroutineScope, LowLevelBotAPIAccessor {
* @throws PermissionDeniedException [Bot] 无权限操作时 * @throws PermissionDeniedException [Bot] 无权限操作时
* @see Bot.recall * @see Bot.recall
*/ */
@JvmSynthetic
suspend inline fun Bot.recall(message: MessageChain) = this.recall(message[MessageSource]) suspend inline fun Bot.recall(message: MessageChain) = this.recall(message[MessageSource])
/** /**
@ -233,6 +237,7 @@ suspend inline fun Bot.recall(message: MessageChain) = this.recall(message[Messa
* @param coroutineContext 额外的 [CoroutineContext] * @param coroutineContext 额外的 [CoroutineContext]
* @see recall * @see recall
*/ */
@JvmSynthetic
inline fun Bot.recallIn( inline fun Bot.recallIn(
source: MessageSource, source: MessageSource,
millis: Long, millis: Long,
@ -249,6 +254,7 @@ inline fun Bot.recallIn(
* @param coroutineContext 额外的 [CoroutineContext] * @param coroutineContext 额外的 [CoroutineContext]
* @see recall * @see recall
*/ */
@JvmSynthetic
inline fun Bot.recallIn( inline fun Bot.recallIn(
message: MessageChain, message: MessageChain,
millis: Long, millis: Long,
@ -265,15 +271,20 @@ inline fun Bot.recallIn(
* *
* @param cause 原因. null 时视为正常关闭, null 时视为异常关闭 * @param cause 原因. null 时视为正常关闭, null 时视为异常关闭
*/ */
@JvmSynthetic
suspend inline fun Bot.closeAndJoin(cause: Throwable? = null) { suspend inline fun Bot.closeAndJoin(cause: Throwable? = null) {
close(cause) close(cause)
coroutineContext[Job]?.join() coroutineContext[Job]?.join()
} }
@JvmSynthetic
inline fun Bot.containsFriend(id: Long): Boolean = this.friends.contains(id) inline fun Bot.containsFriend(id: Long): Boolean = this.friends.contains(id)
@JvmSynthetic
inline fun Bot.containsGroup(id: Long): Boolean = this.groups.contains(id) inline fun Bot.containsGroup(id: Long): Boolean = this.groups.contains(id)
@JvmSynthetic
inline fun Bot.getFriendOrNull(id: Long): QQ? = this.friends.getOrNull(id) inline fun Bot.getFriendOrNull(id: Long): QQ? = this.friends.getOrNull(id)
@JvmSynthetic
inline fun Bot.getGroupOrNull(id: Long): Group? = this.groups.getOrNull(id) inline fun Bot.getGroupOrNull(id: Long): Group? = this.groups.getOrNull(id)

View File

@ -15,12 +15,16 @@ import net.mamoe.mirai.LowLevelAPI
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.recallIn import net.mamoe.mirai.recallIn
import kotlin.jvm.JvmSynthetic
/** /**
* 发送消息后得到的回执. 可用于撤回. * 发送消息后得到的回执. 可用于撤回.
* *
* 此对象持有 [Contact] 的弱引用, [Bot] 离线后将会释放引用, 届时 [target] 将无法访问. * 此对象持有 [Contact] 的弱引用, [Bot] 离线后将会释放引用, 届时 [target] 将无法访问.
* *
* @param source 指代发送出去的消息
* @param target 消息发送对象
*
* @see Group.sendMessage 发送群消息, 返回回执此对象 * @see Group.sendMessage 发送群消息, 返回回执此对象
* @see QQ.sendMessage 发送群消息, 返回回执此对象 * @see QQ.sendMessage 发送群消息, 返回回执此对象
* *
@ -28,11 +32,15 @@ import net.mamoe.mirai.recallIn
* @see MessageReceipt.sourceSequenceId 源序列号 * @see MessageReceipt.sourceSequenceId 源序列号
* @see MessageReceipt.sourceTime 源时间 * @see MessageReceipt.sourceTime 源时间
*/ */
expect open class MessageReceipt<C : Contact>( expect open class MessageReceipt<C : Contact> @OptIn(ExperimentalMessageSource::class) constructor(
source: MessageSource, source: MessageSource,
target: C, target: C,
botAsMember: Member? botAsMember: Member?
) { ) {
/**
* 指代发送出去的消息
*/
@ExperimentalMessageSource
val source: MessageSource val source: MessageSource
/** /**
@ -90,6 +98,8 @@ expect open class MessageReceipt<C : Contact>(
* *
* @see MessageSource.id * @see MessageSource.id
*/ */
@get:JvmSynthetic
@ExperimentalMessageSource
inline val MessageReceipt<*>.sourceId: Long get() = this.source.id inline val MessageReceipt<*>.sourceId: Long get() = this.source.id
/** /**
@ -97,6 +107,8 @@ inline val MessageReceipt<*>.sourceId: Long get() = this.source.id
* *
* @see MessageSource.sequenceId * @see MessageSource.sequenceId
*/ */
@get:JvmSynthetic
@ExperimentalMessageSource
inline val MessageReceipt<*>.sourceSequenceId: Int get() = this.source.sequenceId inline val MessageReceipt<*>.sourceSequenceId: Int get() = this.source.sequenceId
/** /**
@ -104,6 +116,8 @@ inline val MessageReceipt<*>.sourceSequenceId: Int get() = this.source.sequenceI
* *
* @see MessageSource.time * @see MessageSource.time
*/ */
@get:JvmSynthetic
@ExperimentalMessageSource
inline val MessageReceipt<*>.sourceTime: Long get() = this.source.time inline val MessageReceipt<*>.sourceTime: Long get() = this.source.time
suspend inline fun MessageReceipt<out Contact>.quoteReply(message: Message) { suspend inline fun MessageReceipt<out Contact>.quoteReply(message: Message) {

View File

@ -127,6 +127,7 @@ inline fun <reified M : Message> MessageChain.any(): Boolean = this.any { it is
/** /**
* 获取第一个 [M] 类型的 [Message] 实例 * 获取第一个 [M] 类型的 [Message] 实例
*/ */
@OptIn(ExperimentalMessageSource::class)
@JvmSynthetic @JvmSynthetic
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
fun <M : Message> MessageChain.firstOrNull(key: Message.Key<M>): M? = when (key) { fun <M : Message> MessageChain.firstOrNull(key: Message.Key<M>): M? = when (key) {

View File

@ -19,6 +19,12 @@ import kotlin.jvm.JvmMultifileClass
import kotlin.jvm.JvmName import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic import kotlin.jvm.JvmSynthetic
/**
* MessageSource 正计划于 0.32 0.33 或之后进行 API 不兼容的重写.
*/
@RequiresOptIn(message = "MessageSource 正计划于 0.32 或 0.33 或之后进行 API 不兼容的重写", level = RequiresOptIn.Level.WARNING)
annotation class ExperimentalMessageSource
/** /**
* 消息源, 它存在于 [MessageChain] , 用于表示这个消息的来源. * 消息源, 它存在于 [MessageChain] , 用于表示这个消息的来源.
* *
@ -29,6 +35,7 @@ import kotlin.jvm.JvmSynthetic
* @see Bot.recall 撤回一条消息 * @see Bot.recall 撤回一条消息
* @see MessageSource.quote 引用这条消息, 创建 [MessageChain] * @see MessageSource.quote 引用这条消息, 创建 [MessageChain]
*/ */
@ExperimentalMessageSource
interface MessageSource : Message, MessageMetadata { interface MessageSource : Message, MessageMetadata {
companion object Key : Message.Key<MessageSource> companion object Key : Message.Key<MessageSource>
@ -82,6 +89,7 @@ interface MessageSource : Message, MessageMetadata {
* 序列号. 若是机器人发出去的消息, 请先 [确保 sequenceId 可用][MessageSource.ensureSequenceIdAvailable] * 序列号. 若是机器人发出去的消息, 请先 [确保 sequenceId 可用][MessageSource.ensureSequenceIdAvailable]
* @see MessageSource.id * @see MessageSource.id
*/ */
@ExperimentalMessageSource
@get:JvmSynthetic @get:JvmSynthetic
inline val MessageSource.sequenceId: Int inline val MessageSource.sequenceId: Int
get() = (this.id shr 32).toInt() get() = (this.id shr 32).toInt()
@ -90,6 +98,7 @@ inline val MessageSource.sequenceId: Int
* 消息随机数. 由服务器或客户端指定后不能更改. 它是消息 id 的一部分. * 消息随机数. 由服务器或客户端指定后不能更改. 它是消息 id 的一部分.
* @see MessageSource.id * @see MessageSource.id
*/ */
@ExperimentalMessageSource
@get:JvmSynthetic @get:JvmSynthetic
inline val MessageSource.messageRandom: Int inline val MessageSource.messageRandom: Int
get() = this.id.toInt() get() = this.id.toInt()
@ -98,24 +107,33 @@ inline val MessageSource.messageRandom: Int
/** /**
* 消息 id. * 消息 id.
*
* 仅接收到的消息才可以获取这个 id.
*
* @see MessageSource.id * @see MessageSource.id
*/ */
@ExperimentalMessageSource
@get:JvmSynthetic @get:JvmSynthetic
inline val MessageChain.id: Long inline val MessageChain.id: Long
get() = this[MessageSource].id get() = this[MessageSource].id
/** /**
* 消息序列号, 可能来自服务器也可以发送时赋值, 不唯一. * 消息序列号, 可能来自服务器也可以发送时赋值, 不唯一.
*
* 仅接收到的消息才可以获取这个序列号.
*
* @see MessageSource.id * @see MessageSource.id
*/ */
@ExperimentalMessageSource
@get:JvmSynthetic @get:JvmSynthetic
inline val MessageChain.sequenceId: Int inline val MessageChain.sequenceId: Int
get() = this[MessageSource].sequenceId get() = this.getOrNull(MessageSource)?.sequenceId ?: error("Only MessageChain from server has sequenceId")
/** /**
* 消息随机数. 由服务器或客户端指定后不能更改. 它是消息 id 的一部分. * 消息随机数. 由服务器或客户端指定后不能更改. 它是消息 id 的一部分.
* @see MessageSource.id * @see MessageSource.id
*/ */
@ExperimentalMessageSource
@get:JvmSynthetic @get:JvmSynthetic
inline val MessageChain.messageRandom: Int inline val MessageChain.messageRandom: Int
get() = this[MessageSource].messageRandom get() = this.getOrNull(MessageSource)?.messageRandom ?: error("Only MessageChain from server has sequenceId")

View File

@ -29,6 +29,7 @@ import kotlin.jvm.JvmName
* 总是使用 [quote] 来构造这个实例. * 总是使用 [quote] 来构造这个实例.
*/ */
open class QuoteReply open class QuoteReply
@OptIn(ExperimentalMessageSource::class)
@MiraiInternalAPI constructor(val source: MessageSource) : Message, MessageMetadata { @MiraiInternalAPI constructor(val source: MessageSource) : Message, MessageMetadata {
companion object Key : Message.Key<QuoteReply> companion object Key : Message.Key<QuoteReply>
@ -39,7 +40,7 @@ open class QuoteReply
* 用于发送的引用回复. * 用于发送的引用回复.
* 总是使用 [quote] 来构造实例. * 总是使用 [quote] 来构造实例.
*/ */
@OptIn(MiraiInternalAPI::class) @OptIn(MiraiInternalAPI::class, ExperimentalMessageSource::class)
sealed class QuoteReplyToSend sealed class QuoteReplyToSend
@MiraiInternalAPI constructor(source: MessageSource) : QuoteReply(source) { @MiraiInternalAPI constructor(source: MessageSource) : QuoteReply(source) {
class ToGroup(source: MessageSource, val sender: QQ) : QuoteReplyToSend(source) { class ToGroup(source: MessageSource, val sender: QQ) : QuoteReplyToSend(source) {
@ -53,7 +54,7 @@ sealed class QuoteReplyToSend
* 引用这条消息. * 引用这条消息.
* @see sender 消息发送人. * @see sender 消息发送人.
*/ */
@OptIn(MiraiInternalAPI::class) @OptIn(MiraiInternalAPI::class, ExperimentalMessageSource::class)
fun MessageChain.quote(sender: QQ?): QuoteReplyToSend { fun MessageChain.quote(sender: QQ?): QuoteReplyToSend {
this.firstOrNull<MessageSource>()?.let { this.firstOrNull<MessageSource>()?.let {
return it.quote(sender) return it.quote(sender)
@ -65,6 +66,7 @@ fun MessageChain.quote(sender: QQ?): QuoteReplyToSend {
* 引用这条消息. * 引用这条消息.
* @see from 消息来源. 若是好友发送 * @see from 消息来源. 若是好友发送
*/ */
@ExperimentalMessageSource
@OptIn(MiraiInternalAPI::class) @OptIn(MiraiInternalAPI::class)
fun MessageSource.quote(from: QQ?): QuoteReplyToSend { fun MessageSource.quote(from: QQ?): QuoteReplyToSend {
return if (this.groupId != 0L) { return if (this.groupId != 0L) {

View File

@ -7,6 +7,7 @@ import kotlinx.coroutines.io.ByteReadChannel
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.ExperimentalMessageSource
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.message.data.MessageSource
@ -162,6 +163,7 @@ actual abstract class Bot actual constructor() : CoroutineScope, LowLevelBotAPIA
* @see _lowLevelRecallFriendMessage 低级 API * @see _lowLevelRecallFriendMessage 低级 API
* @see _lowLevelRecallGroupMessage 低级 API * @see _lowLevelRecallGroupMessage 低级 API
*/ */
@ExperimentalMessageSource
@JvmSynthetic @JvmSynthetic
actual abstract suspend fun recall(source: MessageSource) actual abstract suspend fun recall(source: MessageSource)

View File

@ -5,6 +5,7 @@ import net.mamoe.mirai.contact.PermissionDeniedException
import net.mamoe.mirai.contact.recall import net.mamoe.mirai.contact.recall
import net.mamoe.mirai.data.AddFriendResult import net.mamoe.mirai.data.AddFriendResult
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.ExperimentalMessageSource
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.message.data.MessageSource
@ -61,6 +62,7 @@ actual abstract class BotJavaFriendlyAPI actual constructor() {
* *
* @see Bot.recall (扩展函数) 接受参数 [MessageChain] * @see Bot.recall (扩展函数) 接受参数 [MessageChain]
*/ */
@ExperimentalMessageSource
@JvmName("recall") @JvmName("recall")
fun __recallBlockingForJava__(source: MessageSource) { fun __recallBlockingForJava__(source: MessageSource) {
runBlocking { recall(source) } runBlocking { recall(source) }
@ -88,6 +90,7 @@ actual abstract class BotJavaFriendlyAPI actual constructor() {
* @param millis 延迟的时间, 单位为毫秒 * @param millis 延迟的时间, 单位为毫秒
* @see recall * @see recall
*/ */
@ExperimentalMessageSource
@JvmName("recallIn") @JvmName("recallIn")
fun __recallIn_MemberForJava__(source: MessageSource, millis: Long) { fun __recallIn_MemberForJava__(source: MessageSource, millis: Long) {
runBlocking { recallIn(source, millis) } runBlocking { recallIn(source, millis) }
@ -148,6 +151,7 @@ actual abstract class BotJavaFriendlyAPI actual constructor() {
/** /**
* 异步调用 [__recallBlockingForJava__] * 异步调用 [__recallBlockingForJava__]
*/ */
@ExperimentalMessageSource
@JvmName("recallAsync") @JvmName("recallAsync")
fun __recallAsyncForJava__(source: MessageSource): Future<Unit> { fun __recallAsyncForJava__(source: MessageSource): Future<Unit> {
return future { recall(source) } return future { recall(source) }

View File

@ -29,7 +29,8 @@ import net.mamoe.mirai.utils.unsafeWeakRef
*/ */
@Suppress("FunctionName") @Suppress("FunctionName")
@OptIn(MiraiInternalAPI::class) @OptIn(MiraiInternalAPI::class)
actual open class MessageReceipt<C : Contact> actual constructor( actual open class MessageReceipt<C : Contact> @OptIn(ExperimentalMessageSource::class)
actual constructor(
actual val source: MessageSource, actual val source: MessageSource,
target: C, target: C,
private val botAsMember: Member? private val botAsMember: Member?
@ -56,6 +57,7 @@ actual open class MessageReceipt<C : Contact> actual constructor(
* @see Bot.recall * @see Bot.recall
* @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时
*/ */
@OptIn(ExperimentalMessageSource::class)
actual suspend fun recall() { actual suspend fun recall() {
@Suppress("BooleanLiteralArgument") @Suppress("BooleanLiteralArgument")
if (_isRecalled.compareAndSet(false, true)) { if (_isRecalled.compareAndSet(false, true)) {
@ -84,6 +86,7 @@ actual open class MessageReceipt<C : Contact> actual constructor(
* [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息. * [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息.
* @see MessageChain.quote 引用一条消息 * @see MessageChain.quote 引用一条消息
*/ */
@OptIn(ExperimentalMessageSource::class)
actual open suspend fun quote(): QuoteReplyToSend { actual open suspend fun quote(): QuoteReplyToSend {
this.source.ensureSequenceIdAvailable() this.source.ensureSequenceIdAvailable()
@OptIn(LowLevelAPI::class) @OptIn(LowLevelAPI::class)
@ -97,6 +100,7 @@ actual open class MessageReceipt<C : Contact> actual constructor(
* *
* @see MessageChain.quote 引用一条消息 * @see MessageChain.quote 引用一条消息
*/ */
@OptIn(ExperimentalMessageSource::class)
@LowLevelAPI @LowLevelAPI
@Suppress("FunctionName") @Suppress("FunctionName")
actual fun _unsafeQuote(): QuoteReplyToSend { actual fun _unsafeQuote(): QuoteReplyToSend {