From 9a482d1926d23340d80d020d01ae682db49912ab Mon Sep 17 00:00:00 2001 From: Him188 Date: Sun, 1 Mar 2020 20:27:30 +0800 Subject: [PATCH] Add Java-friendly APIs for `MessageReceipt` --- .../net/mamoe/mirai/message/MessageReceipt.kt | 142 ++++++++++++++++++ .../net.mamoe.mirai/message/MessageReceipt.kt | 59 ++------ .../net/mamoe/mirai/message/MessageReceipt.kt | 142 ++++++++++++++++++ 3 files changed, 295 insertions(+), 48 deletions(-) create mode 100644 mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt create mode 100644 mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt diff --git a/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt new file mode 100644 index 000000000..3d708e3ed --- /dev/null +++ b/mirai-core/src/androidMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt @@ -0,0 +1,142 @@ +@file:Suppress("unused") + +package net.mamoe.mirai.message + +import kotlinx.atomicfu.atomic +import kotlinx.coroutines.Job +import kotlinx.coroutines.runBlocking +import net.mamoe.mirai.Bot +import net.mamoe.mirai.JavaHappyAPI +import net.mamoe.mirai.LowLevelAPI +import net.mamoe.mirai.contact.* +import net.mamoe.mirai.message.data.* +import net.mamoe.mirai.recallIn +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.getValue +import net.mamoe.mirai.utils.unsafeWeakRef + +/** + * 发送消息后得到的回执. 可用于撤回. + * + * 此对象持有 [Contact] 的弱引用, [Bot] 离线后将会释放引用, 届时 [target] 将无法访问. + * + * @see Group.sendMessage 发送群消息, 返回回执(此对象) + * @see QQ.sendMessage 发送群消息, 返回回执(此对象) + * + * @see MessageReceipt.sourceId 源 id + * @see MessageReceipt.sourceSequenceId 源序列号 + * @see MessageReceipt.sourceTime 源时间 + */ +@Suppress("FunctionName") +@UseExperimental(MiraiInternalAPI::class) +actual open class MessageReceipt actual constructor( + actual val source: MessageSource, + target: C, + private val botAsMember: Member? +) { + init { + require(target is Group || target is QQ) { "target must be either Group or QQ" } + } + + /** + * 发送目标, 为 [Group] 或 [QQ] + */ + actual val target: C by target.unsafeWeakRef() + + /** + * 是否为发送给群的消息的回执 + */ + actual val isToGroup: Boolean = botAsMember != null + + private val _isRecalled = atomic(false) + + /** + * 撤回这条消息. [recall] 或 [recallIn] 只能被调用一次. + * + * @see Bot.recall + * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 + */ + actual suspend fun recall() { + @Suppress("BooleanLiteralArgument") + if (_isRecalled.compareAndSet(false, true)) { + when (val contact = target) { + is Group -> { + contact.bot.recall(source) + } + is QQ -> { + TODO() + } + else -> error("Unknown contact type") + } + } else error("message is already or planned to be recalled") + } + + /** + * 在一段时间后撤回这条消息.. [recall] 或 [recallIn] 只能被调用一次. + * + * @param millis 延迟时间, 单位为毫秒 + * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 + */ + actual fun recallIn(millis: Long): Job { + @Suppress("BooleanLiteralArgument") + if (_isRecalled.compareAndSet(false, true)) { + return when (val contact = target) { + is QQ, + is Group -> contact.bot.recallIn(source, millis) + else -> error("Unknown contact type") + } + } else error("message is already or planned to be recalled") + } + + /** + * [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息. + * @see MessageChain.quote 引用一条消息 + */ + actual open suspend fun quote(): QuoteReplyToSend { + this.source.ensureSequenceIdAvailable() + @UseExperimental(LowLevelAPI::class) + return _unsafeQuote() + } + + /** + * 引用这条消息, 但不会 [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable]. + * 在 sequenceId 可用前就发送这条消息则会导致一个异常. + * 当且仅当用于存储而不用于发送时使用这个方法. + * + * @see MessageChain.quote 引用一条消息 + */ + @LowLevelAPI + @Suppress("FunctionName") + actual fun _unsafeQuote(): QuoteReplyToSend { + return this.source.quote(botAsMember as? QQ) + } + + /** + * 引用这条消息并回复. + * @see MessageChain.quote 引用一条消息 + */ + @JvmName("quoteReplySuspend") + @JvmSynthetic + actual suspend fun quoteReply(message: MessageChain) { + target.sendMessage(this.quote() + message) + } + + + @JavaHappyAPI + @JvmName("quoteReply") + fun __quoteReplyBlockingForJava__(message: Message) { + runBlocking { quoteReply(message) } + } + + @JavaHappyAPI + @JvmName("recall") + fun __recallBlockingForJava__() { + runBlocking { recall() } + } + + @JavaHappyAPI + @JvmName("quote") + fun __quoteBlockingForJava__() { + runBlocking { quote() } + } +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt index 44ab22ed9..380f7b27b 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/MessageReceipt.kt @@ -9,15 +9,12 @@ package net.mamoe.mirai.message -import kotlinx.atomicfu.atomic import kotlinx.coroutines.Job import net.mamoe.mirai.Bot import net.mamoe.mirai.LowLevelAPI import net.mamoe.mirai.contact.* import net.mamoe.mirai.message.data.* import net.mamoe.mirai.recallIn -import net.mamoe.mirai.utils.getValue -import net.mamoe.mirai.utils.unsafeWeakRef /** * 发送消息后得到的回执. 可用于撤回. @@ -31,26 +28,22 @@ import net.mamoe.mirai.utils.unsafeWeakRef * @see MessageReceipt.sourceSequenceId 源序列号 * @see MessageReceipt.sourceTime 源时间 */ -open class MessageReceipt( - val source: MessageSource, +expect open class MessageReceipt( + source: MessageSource, target: C, - private val botAsMember: Member? + botAsMember: Member? ) { - init { - require(target is Group || target is QQ) { "target must be either Group or QQ" } - } + val source: MessageSource /** * 发送目标, 为 [Group] 或 [QQ] */ - val target: C by target.unsafeWeakRef() + val target: C /** * 是否为发送给群的消息的回执 */ - val isToGroup: Boolean = botAsMember != null - - private val _isRecalled = atomic(false) + val isToGroup: Boolean /** * 撤回这条消息. [recall] 或 [recallIn] 只能被调用一次. @@ -58,20 +51,7 @@ open class MessageReceipt( * @see Bot.recall * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 */ - suspend fun recall() { - @Suppress("BooleanLiteralArgument") - if (_isRecalled.compareAndSet(false, true)) { - when (val contact = target) { - is Group -> { - contact.bot.recall(source) - } - is QQ -> { - TODO() - } - else -> error("Unknown contact type") - } - } else error("message is already or planned to be recalled") - } + suspend fun recall() /** * 在一段时间后撤回这条消息.. [recall] 或 [recallIn] 只能被调用一次. @@ -79,26 +59,13 @@ open class MessageReceipt( * @param millis 延迟时间, 单位为毫秒 * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 */ - fun recallIn(millis: Long): Job { - @Suppress("BooleanLiteralArgument") - if (_isRecalled.compareAndSet(false, true)) { - return when (val contact = target) { - is QQ, - is Group -> contact.bot.recallIn(source, millis) - else -> error("Unknown contact type") - } - } else error("message is already or planned to be recalled") - } + fun recallIn(millis: Long): Job /** * [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息. * @see MessageChain.quote 引用一条消息 */ - open suspend fun quote(): QuoteReplyToSend { - this.source.ensureSequenceIdAvailable() - @UseExperimental(LowLevelAPI::class) - return _unsafeQuote() - } + open suspend fun quote(): QuoteReplyToSend /** * 引用这条消息, 但不会 [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable]. @@ -109,17 +76,13 @@ open class MessageReceipt( */ @LowLevelAPI @Suppress("FunctionName") - fun _unsafeQuote(): QuoteReplyToSend { - return this.source.quote(botAsMember as? QQ) - } + fun _unsafeQuote(): QuoteReplyToSend /** * 引用这条消息并回复. * @see MessageChain.quote 引用一条消息 */ - suspend fun quoteReply(message: MessageChain) { - target.sendMessage(this.quote() + message) - } + suspend fun quoteReply(message: MessageChain) } /** diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt new file mode 100644 index 000000000..3d708e3ed --- /dev/null +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/message/MessageReceipt.kt @@ -0,0 +1,142 @@ +@file:Suppress("unused") + +package net.mamoe.mirai.message + +import kotlinx.atomicfu.atomic +import kotlinx.coroutines.Job +import kotlinx.coroutines.runBlocking +import net.mamoe.mirai.Bot +import net.mamoe.mirai.JavaHappyAPI +import net.mamoe.mirai.LowLevelAPI +import net.mamoe.mirai.contact.* +import net.mamoe.mirai.message.data.* +import net.mamoe.mirai.recallIn +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.getValue +import net.mamoe.mirai.utils.unsafeWeakRef + +/** + * 发送消息后得到的回执. 可用于撤回. + * + * 此对象持有 [Contact] 的弱引用, [Bot] 离线后将会释放引用, 届时 [target] 将无法访问. + * + * @see Group.sendMessage 发送群消息, 返回回执(此对象) + * @see QQ.sendMessage 发送群消息, 返回回执(此对象) + * + * @see MessageReceipt.sourceId 源 id + * @see MessageReceipt.sourceSequenceId 源序列号 + * @see MessageReceipt.sourceTime 源时间 + */ +@Suppress("FunctionName") +@UseExperimental(MiraiInternalAPI::class) +actual open class MessageReceipt actual constructor( + actual val source: MessageSource, + target: C, + private val botAsMember: Member? +) { + init { + require(target is Group || target is QQ) { "target must be either Group or QQ" } + } + + /** + * 发送目标, 为 [Group] 或 [QQ] + */ + actual val target: C by target.unsafeWeakRef() + + /** + * 是否为发送给群的消息的回执 + */ + actual val isToGroup: Boolean = botAsMember != null + + private val _isRecalled = atomic(false) + + /** + * 撤回这条消息. [recall] 或 [recallIn] 只能被调用一次. + * + * @see Bot.recall + * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 + */ + actual suspend fun recall() { + @Suppress("BooleanLiteralArgument") + if (_isRecalled.compareAndSet(false, true)) { + when (val contact = target) { + is Group -> { + contact.bot.recall(source) + } + is QQ -> { + TODO() + } + else -> error("Unknown contact type") + } + } else error("message is already or planned to be recalled") + } + + /** + * 在一段时间后撤回这条消息.. [recall] 或 [recallIn] 只能被调用一次. + * + * @param millis 延迟时间, 单位为毫秒 + * @throws IllegalStateException 当此消息已经被撤回或正计划撤回时 + */ + actual fun recallIn(millis: Long): Job { + @Suppress("BooleanLiteralArgument") + if (_isRecalled.compareAndSet(false, true)) { + return when (val contact = target) { + is QQ, + is Group -> contact.bot.recallIn(source, millis) + else -> error("Unknown contact type") + } + } else error("message is already or planned to be recalled") + } + + /** + * [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable] 然后引用这条消息. + * @see MessageChain.quote 引用一条消息 + */ + actual open suspend fun quote(): QuoteReplyToSend { + this.source.ensureSequenceIdAvailable() + @UseExperimental(LowLevelAPI::class) + return _unsafeQuote() + } + + /** + * 引用这条消息, 但不会 [确保 sequenceId可用][MessageSource.ensureSequenceIdAvailable]. + * 在 sequenceId 可用前就发送这条消息则会导致一个异常. + * 当且仅当用于存储而不用于发送时使用这个方法. + * + * @see MessageChain.quote 引用一条消息 + */ + @LowLevelAPI + @Suppress("FunctionName") + actual fun _unsafeQuote(): QuoteReplyToSend { + return this.source.quote(botAsMember as? QQ) + } + + /** + * 引用这条消息并回复. + * @see MessageChain.quote 引用一条消息 + */ + @JvmName("quoteReplySuspend") + @JvmSynthetic + actual suspend fun quoteReply(message: MessageChain) { + target.sendMessage(this.quote() + message) + } + + + @JavaHappyAPI + @JvmName("quoteReply") + fun __quoteReplyBlockingForJava__(message: Message) { + runBlocking { quoteReply(message) } + } + + @JavaHappyAPI + @JvmName("recall") + fun __recallBlockingForJava__() { + runBlocking { recall() } + } + + @JavaHappyAPI + @JvmName("quote") + fun __quoteBlockingForJava__() { + runBlocking { quote() } + } +} \ No newline at end of file