mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-13 06:30:13 +08:00
Introduce ContactMessage
to replace MessagePacket<*, *>
This commit is contained in:
parent
3773548983
commit
32553fad2b
@ -2,6 +2,13 @@
|
||||
|
||||
开发版本. 频繁更新, 不保证高稳定性
|
||||
|
||||
## `0.32.0`
|
||||
- 将部分 internal API 从 `mirai-core` 移至 `mirai-core-qqandroid`
|
||||
- 将部分意外 public 的 API 改为 internal.
|
||||
- 使用 Kotlin 1.3.71, 兼容原使用 Kotlin 1.4-M1 编译的代码.
|
||||
- 优化 `BotConfiguration`, 去掉 DSL 操作, 使用 `fileBasedDeviceInfo(filename)` 等函数替代. (兼容原操作方式, 计划于 `0.34.0` 删除)
|
||||
- 调整长消息判定权重, 具体为: Chinese char=4, English char=1, Quote=700, Image=800, 其他消息类型转换为字符串后判断长度.
|
||||
|
||||
## `0.31.4` 2020/3/31
|
||||
- 修复 At 在手机上显示错误的问题
|
||||
|
||||
|
@ -75,7 +75,7 @@ internal class QQImpl(
|
||||
|
||||
@JvmSynthetic
|
||||
@Suppress("DuplicatedCode")
|
||||
override suspend fun sendMessage(message: Message): MessageReceipt<out QQ> {
|
||||
override suspend fun sendMessage(message: Message): MessageReceipt<QQ> {
|
||||
val event = MessageSendEvent.FriendMessageSendEvent(this, message.asMessageChain()).broadcast()
|
||||
if (event.isCancelled) {
|
||||
throw EventCancelledException("cancelled by FriendMessageSendEvent")
|
||||
|
@ -66,7 +66,7 @@ actual abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI() {
|
||||
* @return 消息回执. 可 [引用回复][MessageReceipt.quote](仅群聊)或 [撤回][MessageReceipt.recall] 这条消息.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract suspend fun sendMessage(message: Message): MessageReceipt<out Contact>
|
||||
actual abstract suspend fun sendMessage(message: Message): MessageReceipt<Contact>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
|
@ -62,14 +62,14 @@ actual abstract class ContactJavaFriendlyAPI {
|
||||
*/
|
||||
@Throws(EventCancelledException::class, IllegalStateException::class)
|
||||
@JvmName("sendMessage")
|
||||
open fun __sendMessageBlockingForJava__(message: Message): MessageReceipt<out Contact> {
|
||||
open fun __sendMessageBlockingForJava__(message: Message): MessageReceipt<Contact> {
|
||||
return runBlocking {
|
||||
sendMessage(message)
|
||||
}
|
||||
}
|
||||
|
||||
@JvmName("sendMessage")
|
||||
open fun __sendMessageBlockingForJava__(message: String): MessageReceipt<out Contact> {
|
||||
open fun __sendMessageBlockingForJava__(message: String): MessageReceipt<Contact> {
|
||||
return runBlocking { sendMessage(message) }
|
||||
}
|
||||
|
||||
@ -143,7 +143,7 @@ actual abstract class ContactJavaFriendlyAPI {
|
||||
* @see Contact.sendMessage
|
||||
*/
|
||||
@JvmName("sendMessageAsync")
|
||||
open fun __sendMessageAsyncForJava__(message: Message): Future<MessageReceipt<out Contact>> {
|
||||
open fun __sendMessageAsyncForJava__(message: Message): Future<MessageReceipt<Contact>> {
|
||||
return future { sendMessage(message) }
|
||||
}
|
||||
|
||||
@ -152,7 +152,7 @@ actual abstract class ContactJavaFriendlyAPI {
|
||||
* @see Contact.sendMessage
|
||||
*/
|
||||
@JvmName("sendMessageAsync")
|
||||
open fun __sendMessageAsyncForJava__(message: String): Future<MessageReceipt<out Contact>> {
|
||||
open fun __sendMessageAsyncForJava__(message: String): Future<MessageReceipt<Contact>> {
|
||||
return future { sendMessage(message) }
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ actual abstract class QQ : Contact(), CoroutineScope {
|
||||
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract override suspend fun sendMessage(message: Message): MessageReceipt<out QQ>
|
||||
actual abstract override suspend fun sendMessage(message: Message): MessageReceipt<QQ>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
|
@ -9,36 +9,48 @@
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import android.graphics.Bitmap
|
||||
import kotlinx.io.core.Input
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.QQ
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* 平台相关扩展
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual constructor() : MessagePacketBase<TSender, TSubject>() {
|
||||
// suspend inline fun uploadImage(image: Bitmap): Image = subject.uploadImage(image)
|
||||
//suspend inline fun uploadImage(image: URL): Image = subject.uploadImage(image)
|
||||
//suspend inline fun uploadImage(image: Input): Image = subject.uploadImage(image)
|
||||
//suspend inline fun uploadImage(image: InputStream): Image = subject.uploadImage(image)
|
||||
//suspend inline fun uploadImage(image: File): Image = subject.uploadImage(image)
|
||||
actual sealed class MessagePacket<TSender : QQ, TSubject : Contact> actual constructor() :
|
||||
MessagePacketBase<TSender, TSubject>() {
|
||||
suspend inline fun uploadImage(image: Bitmap): Image = subject.uploadImage(image)
|
||||
suspend inline fun uploadImage(image: URL): Image = subject.uploadImage(image)
|
||||
suspend inline fun uploadImage(image: Input): Image = subject.uploadImage(image)
|
||||
suspend inline fun uploadImage(image: InputStream): Image = subject.uploadImage(image)
|
||||
suspend inline fun uploadImage(image: File): Image = subject.uploadImage(image)
|
||||
|
||||
//// suspend inline fun sendImage(image: Bitmap) = subject.sendImage(image)
|
||||
//suspend inline fun sendImage(image: URL) = subject.sendImage(image)
|
||||
//suspend inline fun sendImage(image: Input) = subject.sendImage(image)
|
||||
//suspend inline fun sendImage(image: InputStream) = subject.sendImage(image)
|
||||
//suspend inline fun sendImage(image: File) = subject.sendImage(image)
|
||||
suspend inline fun sendImage(image: Bitmap): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
suspend inline fun sendImage(image: URL): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
suspend inline fun sendImage(image: Input): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
suspend inline fun sendImage(image: InputStream): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
suspend inline fun sendImage(image: File): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
|
||||
//// suspend inline fun Bitmap.upload(): Image = upload(subject)
|
||||
//suspend inline fun URL.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
//suspend inline fun Input.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
//suspend inline fun InputStream.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
//suspend inline fun File.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
suspend inline fun Bitmap.upload(): Image = upload(subject)
|
||||
suspend inline fun URL.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
suspend inline fun Input.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
suspend inline fun InputStream.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
suspend inline fun File.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
|
||||
//// suspend inline fun Bitmap.send() = sendTo(subject)
|
||||
//suspend inline fun URL.sendAsImage() = sendAsImageTo(subject)
|
||||
//suspend inline fun Input.sendAsImage() = sendAsImageTo(subject)
|
||||
//suspend inline fun InputStream.sendAsImage() = sendAsImageTo(subject)
|
||||
//suspend inline fun File.sendAsImage() = sendAsImageTo(subject)
|
||||
suspend inline fun Bitmap.send(): MessageReceipt<TSubject> = sendTo(subject)
|
||||
suspend inline fun URL.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
suspend inline fun Input.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
suspend inline fun InputStream.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
suspend inline fun File.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
}
|
@ -29,7 +29,7 @@ import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
actual open class MessageReceipt<C : Contact> @OptIn(ExperimentalMessageSource::class)
|
||||
actual open class MessageReceipt<out C : Contact> @OptIn(ExperimentalMessageSource::class)
|
||||
actual constructor(
|
||||
actual val source: MessageSource,
|
||||
target: C,
|
||||
|
@ -69,7 +69,7 @@ expect abstract class Contact() : CoroutineScope, ContactJavaFriendlyAPI {
|
||||
* @return 消息回执. 可 [引用回复][MessageReceipt.quote](仅群聊)或 [撤回][MessageReceipt.recall] 这条消息.
|
||||
*/
|
||||
@JvmSynthetic
|
||||
abstract suspend fun sendMessage(message: Message): MessageReceipt<out Contact>
|
||||
abstract suspend fun sendMessage(message: Message): MessageReceipt<Contact>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
|
@ -99,7 +99,7 @@ expect abstract class QQ() : Contact, CoroutineScope {
|
||||
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
|
||||
*/
|
||||
@JvmSynthetic
|
||||
abstract override suspend fun sendMessage(message: Message): MessageReceipt<out QQ>
|
||||
abstract override suspend fun sendMessage(message: Message): MessageReceipt<QQ>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
|
@ -10,7 +10,7 @@
|
||||
package net.mamoe.mirai.event
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.message.MessagePacket
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
import net.mamoe.mirai.message.isContextIdenticalWith
|
||||
@ -59,7 +59,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
*/
|
||||
@SinceMirai("0.29.0")
|
||||
@Suppress("unused")
|
||||
suspend inline fun <reified T : MessagePacket<*, *>> T.whileSelectMessages(
|
||||
suspend inline fun <reified T : ContactMessage> T.whileSelectMessages(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
|
||||
) = whileSelectMessagesImpl(timeoutMillis, selectBuilder)
|
||||
@ -71,7 +71,7 @@ suspend inline fun <reified T : MessagePacket<*, *>> T.whileSelectMessages(
|
||||
@MiraiExperimentalAPI
|
||||
@SinceMirai("0.29.0")
|
||||
@JvmName("selectMessages1")
|
||||
suspend inline fun <reified T : MessagePacket<*, *>> T.selectMessagesUnit(
|
||||
suspend inline fun <reified T : ContactMessage> T.selectMessagesUnit(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, Unit>.() -> Unit
|
||||
) = selectMessagesImpl(timeoutMillis, true, selectBuilder)
|
||||
@ -100,7 +100,7 @@ suspend inline fun <reified T : MessagePacket<*, *>> T.selectMessagesUnit(
|
||||
@SinceMirai("0.29.0")
|
||||
@Suppress("unused") // false positive
|
||||
// @BuilderInference // https://youtrack.jetbrains.com/issue/KT-37716
|
||||
suspend inline fun <reified T : MessagePacket<*, *>, R> T.selectMessages(
|
||||
suspend inline fun <reified T : ContactMessage, R> T.selectMessages(
|
||||
timeoutMillis: Long = -1,
|
||||
// @BuilderInference
|
||||
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, R>.() -> Unit
|
||||
@ -114,7 +114,7 @@ suspend inline fun <reified T : MessagePacket<*, *>, R> T.selectMessages(
|
||||
* @see MessageSelectBuilderUnit 查看上层 API
|
||||
*/
|
||||
@SinceMirai("0.29.0")
|
||||
abstract class MessageSelectBuilder<M : MessagePacket<*, *>, R> @PublishedApi internal constructor(
|
||||
abstract class MessageSelectBuilder<M : ContactMessage, R> @PublishedApi internal constructor(
|
||||
ownerMessagePacket: M,
|
||||
stub: Any?,
|
||||
subscriber: (M.(String) -> Boolean, MessageListener<M, Any?>) -> Unit
|
||||
@ -194,7 +194,7 @@ abstract class MessageSelectBuilder<M : MessagePacket<*, *>, R> @PublishedApi in
|
||||
* @see MessageSubscribersBuilder 查看上层 API
|
||||
*/
|
||||
@SinceMirai("0.29.0")
|
||||
abstract class MessageSelectBuilderUnit<M : MessagePacket<*, *>, R> @PublishedApi internal constructor(
|
||||
abstract class MessageSelectBuilderUnit<M : ContactMessage, R> @PublishedApi internal constructor(
|
||||
private val ownerMessagePacket: M,
|
||||
stub: Any?,
|
||||
subscriber: (M.(String) -> Boolean, MessageListener<M, Any?>) -> Unit
|
||||
@ -373,7 +373,7 @@ internal val SELECT_MESSAGE_STUB = Any()
|
||||
@PublishedApi
|
||||
@BuilderInference
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
internal suspend inline fun <reified T : MessagePacket<*, *>, R> T.selectMessagesImpl(
|
||||
internal suspend inline fun <reified T : ContactMessage, R> T.selectMessagesImpl(
|
||||
timeoutMillis: Long = -1,
|
||||
isUnit: Boolean,
|
||||
@BuilderInference
|
||||
@ -465,7 +465,7 @@ internal suspend inline fun <reified T : MessagePacket<*, *>, R> T.selectMessage
|
||||
|
||||
@Suppress("unused")
|
||||
@PublishedApi
|
||||
internal suspend inline fun <reified T : MessagePacket<*, *>> T.whileSelectMessagesImpl(
|
||||
internal suspend inline fun <reified T : ContactMessage> T.whileSelectMessagesImpl(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
|
||||
) {
|
||||
|
@ -20,9 +20,9 @@ import net.mamoe.mirai.contact.isAdministrator
|
||||
import net.mamoe.mirai.contact.isOperator
|
||||
import net.mamoe.mirai.contact.isOwner
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.FriendMessage
|
||||
import net.mamoe.mirai.message.GroupMessage
|
||||
import net.mamoe.mirai.message.MessagePacket
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.first
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
@ -34,7 +34,7 @@ import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.js.JsName
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder<MessagePacket<*, *>, Listener<MessagePacket<*, *>>, Unit, Unit>
|
||||
typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder<ContactMessage, Listener<ContactMessage>, Unit, Unit>
|
||||
|
||||
/**
|
||||
* 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话.
|
||||
@ -53,7 +53,7 @@ fun <R> CoroutineScope.subscribeMessages(
|
||||
}
|
||||
|
||||
return MessagePacketSubscribersBuilder(Unit)
|
||||
{ filter, messageListener: MessageListener<MessagePacket<*, *>, Unit> ->
|
||||
{ filter, messageListener: MessageListener<ContactMessage, Unit> ->
|
||||
// subscribeAlways 即注册一个监听器. 这个监听器收到消息后就传递给 [messageListener]
|
||||
// messageListener 即为 DSL 里 `contains(...) { }`, `startsWith(...) { }` 的代码块.
|
||||
subscribeAlways(coroutineContext, concurrencyKind) {
|
||||
@ -245,7 +245,7 @@ inline fun <reified E : BotEvent> Bot.incoming(
|
||||
* 消息事件的处理器.
|
||||
*
|
||||
* 注:
|
||||
* 接受者 T 为 [MessagePacket]
|
||||
* 接受者 T 为 [ContactMessage]
|
||||
* 参数 String 为 转为字符串了的消息 ([Message.toString])
|
||||
*/
|
||||
typealias MessageListener<T, R> = @MessageDsl suspend T.(String) -> R
|
||||
@ -262,7 +262,7 @@ typealias MessageListener<T, R> = @MessageDsl suspend T.(String) -> R
|
||||
*/
|
||||
@Suppress("unused", "DSL_SCOPE_VIOLATION_WARNING")
|
||||
@MessageDsl
|
||||
open class MessageSubscribersBuilder<M : MessagePacket<*, *>, out Ret, R : RR, RR>(
|
||||
open class MessageSubscribersBuilder<M : ContactMessage, out Ret, R : RR, RR>(
|
||||
val stub: RR,
|
||||
/**
|
||||
* invoke 这个 lambda 时, 它将会把 [消息事件的处理器][MessageListener] 注册给事件, 并返回注册完成返回的监听器.
|
||||
|
@ -19,7 +19,7 @@ import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
class FriendMessage(
|
||||
sender: QQ,
|
||||
override val message: MessageChain
|
||||
) : MessagePacket<QQ, QQ>(), BroadcastControllable {
|
||||
) : ContactMessage(), BroadcastControllable {
|
||||
override val sender: QQ by sender.unsafeWeakRef()
|
||||
override val bot: Bot get() = sender.bot
|
||||
override val subject: QQ get() = sender
|
||||
|
@ -27,7 +27,7 @@ class GroupMessage(
|
||||
val permission: MemberPermission,
|
||||
sender: Member,
|
||||
override val message: MessageChain
|
||||
) : MessagePacket<Member, Group>(), Event {
|
||||
) : ContactMessage(), Event {
|
||||
override val sender: Member by sender.unsafeWeakRef()
|
||||
val group: Group get() = sender.group
|
||||
override val bot: Bot get() = sender.bot
|
||||
|
@ -7,7 +7,14 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("EXPERIMENTAL_UNSIGNED_LITERALS", "EXPERIMENTAL_API_USAGE", "unused")
|
||||
@file:Suppress(
|
||||
"EXPERIMENTAL_UNSIGNED_LITERALS",
|
||||
"EXPERIMENTAL_API_USAGE",
|
||||
"unused",
|
||||
"INVISIBLE_REFERENCE",
|
||||
"INVISIBLE_MEMBER"
|
||||
)
|
||||
@file:OptIn(MiraiInternalAPI::class)
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
@ -33,20 +40,42 @@ import net.mamoe.mirai.utils.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* 一条消息事件.
|
||||
* 它是一个 [BotEvent], 因此可以被 [监听][Bot.subscribe]
|
||||
*
|
||||
* 支持的消息类型:
|
||||
* [GroupMessage]
|
||||
* [FriendMessage]
|
||||
*
|
||||
* @see isContextIdenticalWith 判断语境是否相同
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@SinceMirai("0.32.0")
|
||||
abstract class ContactMessage : MessagePacket<QQ, Contact>(), BotEvent
|
||||
|
||||
/**
|
||||
* 一条从服务器接收到的消息事件.
|
||||
* 请查看各平台的 `actual` 实现的说明.
|
||||
*/
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
expect abstract class MessagePacket<TSender : QQ, TSubject : Contact>() : MessagePacketBase<TSender, TSubject>
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
expect sealed class MessagePacket<TSender : QQ, TSubject : Contact>() : MessagePacketBase<TSender, TSubject>
|
||||
|
||||
/**
|
||||
* 仅内部使用, 请使用 [MessagePacket]
|
||||
* 仅内部使用, 请使用 [ContactMessage]
|
||||
*/ // Tips: 在 IntelliJ 中 (左侧边栏) 打开 `Structure`, 可查看类结构
|
||||
@Deprecated(
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
||||
@MiraiInternalAPI
|
||||
abstract class MessagePacketBase<TSender : QQ, TSubject : Contact> : Packet, BotEvent {
|
||||
abstract class MessagePacketBase<out TSender : QQ, out TSubject : Contact> : Packet, BotEvent {
|
||||
/**
|
||||
* 接受到这条消息的
|
||||
*/
|
||||
@ -91,11 +120,6 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact> : Packet, Bot
|
||||
suspend inline fun reply(plain: String): MessageReceipt<TSubject> =
|
||||
subject.sendMessage(plain.toMessage().asMessageChain()) as MessageReceipt<TSubject>
|
||||
|
||||
@JvmName("reply1")
|
||||
suspend inline fun String.reply(): MessageReceipt<TSubject> = reply(this)
|
||||
|
||||
@JvmName("reply1")
|
||||
suspend inline fun Message.reply(): MessageReceipt<TSubject> = reply(this)
|
||||
// endregion
|
||||
|
||||
// region 撤回
|
||||
@ -131,6 +155,7 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact> : Packet, Bot
|
||||
// endregion
|
||||
|
||||
|
||||
// region 引用回复
|
||||
/**
|
||||
* 给这个消息事件的主体发送引用回复消息
|
||||
* 对于好友消息事件, 这个方法将会给好友 ([subject]) 发送消息
|
||||
@ -151,12 +176,11 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact> : Packet, Bot
|
||||
@JvmName("reply2")
|
||||
suspend inline fun MessageChain.quoteReply(): MessageReceipt<TSubject> = quoteReply(this)
|
||||
|
||||
/**
|
||||
* 引用这个消息
|
||||
*/
|
||||
@ExperimentalMessageSource
|
||||
inline fun MessageChain.quote(): QuoteReplyToSend = this.quote(sender)
|
||||
|
||||
// endregion
|
||||
|
||||
operator fun <M : Message> get(at: Message.Key<M>): M {
|
||||
return this.message[at]
|
||||
}
|
||||
@ -189,13 +213,22 @@ abstract class MessagePacketBase<TSender : QQ, TSubject : Contact> : Packet, Bot
|
||||
*/
|
||||
suspend inline fun Image.channel(): ByteReadChannel = bot.openChannel(this)
|
||||
// endregion
|
||||
|
||||
|
||||
@Deprecated("use reply(String) for clear semantics", ReplaceWith("reply(this)"))
|
||||
@JvmName("reply1")
|
||||
suspend inline fun String.reply(): MessageReceipt<TSubject> = reply(this)
|
||||
|
||||
@Deprecated("use reply(String) for clear semantics", ReplaceWith("reply(this)"))
|
||||
@JvmName("reply1")
|
||||
suspend inline fun Message.reply(): MessageReceipt<TSubject> = reply(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个 [MessagePacket] 的 [MessagePacket.sender] 和 [MessagePacket.subject] 是否相同
|
||||
*/
|
||||
@SinceMirai("0.29.0")
|
||||
fun MessagePacket<*, *>.isContextIdenticalWith(another: MessagePacket<*, *>): Boolean {
|
||||
fun ContactMessage.isContextIdenticalWith(another: ContactMessage): Boolean {
|
||||
return this.sender == another.sender && this.subject == another.subject && this.bot == another.bot
|
||||
}
|
||||
|
||||
@ -209,7 +242,8 @@ fun MessagePacket<*, *>.isContextIdenticalWith(another: MessagePacket<*, *>): Bo
|
||||
*
|
||||
* @see subscribingGet
|
||||
*/
|
||||
suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessage(
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessage(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): MessageChain {
|
||||
@ -229,7 +263,8 @@ suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessage(
|
||||
*
|
||||
* @see subscribingGetOrNull
|
||||
*/
|
||||
suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessageOrNull(
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessageOrNull(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): MessageChain? {
|
||||
@ -247,7 +282,8 @@ suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessageOrNull(
|
||||
*
|
||||
* @see subscribingGet
|
||||
*/
|
||||
suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessage(
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessage(
|
||||
timeoutMillis: Long = -1
|
||||
): MessageChain {
|
||||
return subscribingGet<P, P>(timeoutMillis) {
|
||||
@ -259,7 +295,8 @@ suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessage(
|
||||
* @see nextMessage
|
||||
* @throws TimeoutCancellationException
|
||||
*/
|
||||
inline fun <reified P : MessagePacket<*, *>> P.nextMessageAsync(
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : ContactMessage> P.nextMessageAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<MessageChain> {
|
||||
@ -273,7 +310,8 @@ inline fun <reified P : MessagePacket<*, *>> P.nextMessageAsync(
|
||||
/**
|
||||
* @see nextMessage
|
||||
*/
|
||||
inline fun <reified P : MessagePacket<*, *>> P.nextMessageAsync(
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : ContactMessage> P.nextMessageAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
@ -296,7 +334,8 @@ inline fun <reified P : MessagePacket<*, *>> P.nextMessageAsync(
|
||||
*
|
||||
* @see subscribingGetOrNull
|
||||
*/
|
||||
suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessageOrNull(
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessageOrNull(
|
||||
timeoutMillis: Long = -1
|
||||
): MessageChain? {
|
||||
return subscribingGetOrNull<P, P>(timeoutMillis) {
|
||||
@ -307,7 +346,8 @@ suspend inline fun <reified P : MessagePacket<*, *>> P.nextMessageOrNull(
|
||||
/**
|
||||
* @see nextMessageOrNull
|
||||
*/
|
||||
inline fun <reified P : MessagePacket<*, *>> P.nextMessageOrNullAsync(
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : ContactMessage> P.nextMessageOrNullAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<MessageChain?> {
|
||||
@ -329,21 +369,23 @@ inline fun <reified P : MessagePacket<*, *>> P.nextMessageOrNullAsync(
|
||||
* @see whileSelectMessages
|
||||
* @see selectMessages
|
||||
*/
|
||||
suspend inline fun <reified M : Message> MessagePacket<*, *>.nextMessageContaining(
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified M : Message> ContactMessage.nextMessageContaining(
|
||||
timeoutMillis: Long = -1
|
||||
): M {
|
||||
return subscribingGet<MessagePacket<*, *>, MessagePacket<*, *>>(timeoutMillis) {
|
||||
return subscribingGet<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContaining) }
|
||||
}.message.first()
|
||||
}
|
||||
|
||||
inline fun <reified M : Message> MessagePacket<*, *>.nextMessageContainingAsync(
|
||||
@JvmSynthetic
|
||||
inline fun <reified M : Message> ContactMessage.nextMessageContainingAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<M> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
subscribingGet<MessagePacket<*, *>, MessagePacket<*, *>>(timeoutMillis) {
|
||||
subscribingGet<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingAsync) }
|
||||
}.message.first<M>()
|
||||
}
|
||||
@ -359,21 +401,30 @@ inline fun <reified M : Message> MessagePacket<*, *>.nextMessageContainingAsync(
|
||||
*
|
||||
* @see subscribingGetOrNull
|
||||
*/
|
||||
suspend inline fun <reified M : Message> MessagePacket<*, *>.nextMessageContainingOrNull(
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified M : Message> ContactMessage.nextMessageContainingOrNull(
|
||||
timeoutMillis: Long = -1
|
||||
): M? {
|
||||
return subscribingGetOrNull<MessagePacket<*, *>, MessagePacket<*, *>>(timeoutMillis) {
|
||||
return subscribingGetOrNull<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingOrNull) }
|
||||
}?.message?.first()
|
||||
}
|
||||
|
||||
inline fun <reified M : Message> MessagePacket<*, *>.nextMessageContainingOrNullAsync(
|
||||
@JvmSynthetic
|
||||
inline fun <reified M : Message> ContactMessage.nextMessageContainingOrNullAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<M?> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
subscribingGetOrNull<MessagePacket<*, *>, MessagePacket<*, *>>(timeoutMillis) {
|
||||
subscribingGetOrNull<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingOrNullAsync) }
|
||||
}?.message?.first<M>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(level = DeprecationLevel.HIDDEN, message = "for binary compatibility")
|
||||
fun MessagePacket<*, *>.isContextIdenticalWith(another: MessagePacket<*, *>): Boolean {
|
||||
return (this as ContactMessage).isContextIdenticalWith(another as ContactMessage)
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
* @see MessageReceipt.sourceSequenceId 源序列号
|
||||
* @see MessageReceipt.sourceTime 源时间
|
||||
*/
|
||||
expect open class MessageReceipt<C : Contact> @OptIn(ExperimentalMessageSource::class) constructor(
|
||||
expect open class MessageReceipt<out C : Contact> @OptIn(ExperimentalMessageSource::class) constructor(
|
||||
source: MessageSource,
|
||||
target: C,
|
||||
botAsMember: Member?
|
||||
@ -100,7 +100,8 @@ expect open class MessageReceipt<C : Contact> @OptIn(ExperimentalMessageSource::
|
||||
*/
|
||||
@get:JvmSynthetic
|
||||
@ExperimentalMessageSource
|
||||
inline val MessageReceipt<*>.sourceId: Long get() = this.source.id
|
||||
inline val MessageReceipt<*>.sourceId: Long
|
||||
get() = this.source.id
|
||||
|
||||
/**
|
||||
* 获取源消息 [MessageSource.sequenceId]
|
||||
@ -109,7 +110,8 @@ inline val MessageReceipt<*>.sourceId: Long get() = this.source.id
|
||||
*/
|
||||
@get:JvmSynthetic
|
||||
@ExperimentalMessageSource
|
||||
inline val MessageReceipt<*>.sourceSequenceId: Int get() = this.source.sequenceId
|
||||
inline val MessageReceipt<*>.sourceSequenceId: Int
|
||||
get() = this.source.sequenceId
|
||||
|
||||
/**
|
||||
* 获取源消息 [MessageSource.time]
|
||||
@ -118,13 +120,14 @@ inline val MessageReceipt<*>.sourceSequenceId: Int get() = this.source.sequenceI
|
||||
*/
|
||||
@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<*>.quoteReply(message: Message) {
|
||||
return this.quoteReply(message.asMessageChain())
|
||||
}
|
||||
|
||||
suspend inline fun MessageReceipt<out Contact>.quoteReply(message: String) {
|
||||
suspend inline fun MessageReceipt<*>.quoteReply(message: String) {
|
||||
return this.quoteReply(message.toMessage().asMessageChain())
|
||||
}
|
||||
|
||||
|
@ -14,4 +14,4 @@ package net.mamoe.mirai.utils
|
||||
*/
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class LazyProperty
|
||||
internal annotation class LazyProperty
|
@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Copyright 2020 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/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("unused", "NOTHING_TO_INLINE")
|
||||
|
||||
package net.mamoe.mirai.utils
|
||||
|
||||
/*
|
||||
|
||||
/**
|
||||
* SoftRef that `getValue` for delegation throws an [IllegalStateException] if the referent is released by GC. Therefore it returns notnull value only
|
||||
*/
|
||||
class UnsafeSoftRef<T>(private val softRef: SoftRef<T>) {
|
||||
fun get(): T = softRef.get() ?: error("SoftRef is released")
|
||||
fun clear() = softRef.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides delegate value.
|
||||
*
|
||||
* ```kotlin
|
||||
* val bot: Bot by param.unsafeSoftRef()
|
||||
* ```
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline operator fun <T> UnsafeSoftRef<T>.getValue(thisRef: Any?, property: KProperty<*>): T = get()
|
||||
|
||||
/**
|
||||
* Soft Reference.
|
||||
* On JVM, it is implemented as a typealias referring to `SoftReference` from JDK.
|
||||
*
|
||||
* Details:
|
||||
* On JVM, instances of objects are stored in the JVM Heap and are accessed via references.
|
||||
* GC(garbage collection) can automatically collect and release the memory used by objects that are not directly referred by any other.
|
||||
* [SoftRef] will keep the reference until JVM run out of memory.
|
||||
*
|
||||
* @see softRef provides a SoftRef
|
||||
* @see unsafeSoftRef provides a UnsafeSoftRef
|
||||
*/
|
||||
@SinceMirai("0.32.0")
|
||||
expect class SoftRef<T>(referent: T) {
|
||||
fun get(): T?
|
||||
fun clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that the property is delegated by a [SoftRef]
|
||||
*
|
||||
* @see softRef
|
||||
*/
|
||||
@Target(AnnotationTarget.PROPERTY)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class SoftRefProperty
|
||||
|
||||
/**
|
||||
* Provides a soft reference to [this]
|
||||
* The `getValue` for delegation returns [this] when [this] is not released by GC
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <T> T.softRef(): SoftRef<T> = SoftRef(this)
|
||||
|
||||
/**
|
||||
* Constructs an unsafe inline delegate for [this]
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <T> SoftRef<T>.unsafe(): UnsafeSoftRef<T> = UnsafeSoftRef(this)
|
||||
|
||||
/**
|
||||
* Provides a soft reference to [this].
|
||||
* The `getValue` for delegation throws an [IllegalStateException] if the referent is released by GC. Therefore it returns notnull value only
|
||||
*
|
||||
* **UNSTABLE API**: It is strongly suggested not to use this api
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <T> T.unsafeSoftRef(): UnsafeSoftRef<T> = UnsafeSoftRef(this.softRef())
|
||||
|
||||
/**
|
||||
* Provides delegate value.
|
||||
*
|
||||
* ```kotlin
|
||||
* val bot: Bot? by param.softRef()
|
||||
* ```
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline operator fun <T> SoftRef<T>.getValue(thisRef: Any?, property: KProperty<*>): T? = this.get()
|
||||
|
||||
/**
|
||||
* Call the block if the referent is absent
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <T, R> SoftRef<T>.ifAbsent(block: (T) -> R): R? = this.get()?.let(block)
|
||||
|
||||
*/
|
@ -65,7 +65,7 @@ actual abstract class Contact : CoroutineScope, ContactJavaFriendlyAPI() {
|
||||
* @return 消息回执. 可 [引用回复][MessageReceipt.quote](仅群聊)或 [撤回][MessageReceipt.recall] 这条消息.
|
||||
*/
|
||||
@JvmSynthetic //
|
||||
actual abstract suspend fun sendMessage(message: Message): MessageReceipt<out Contact>
|
||||
actual abstract suspend fun sendMessage(message: Message): MessageReceipt<Contact>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
|
@ -61,12 +61,12 @@ actual abstract class ContactJavaFriendlyAPI {
|
||||
*/
|
||||
@Throws(EventCancelledException::class, IllegalStateException::class)
|
||||
@JvmName("sendMessage")
|
||||
open fun __sendMessageBlockingForJava__(message: Message): MessageReceipt<out Contact> {
|
||||
open fun __sendMessageBlockingForJava__(message: Message): MessageReceipt<Contact> {
|
||||
return runBlocking { sendMessage(message) }
|
||||
}
|
||||
|
||||
@JvmName("sendMessage")
|
||||
open fun __sendMessageBlockingForJava__(message: String): MessageReceipt<out Contact> {
|
||||
open fun __sendMessageBlockingForJava__(message: String): MessageReceipt<Contact> {
|
||||
return runBlocking { sendMessage(message) }
|
||||
}
|
||||
|
||||
@ -140,7 +140,7 @@ actual abstract class ContactJavaFriendlyAPI {
|
||||
* @see Contact.sendMessage
|
||||
*/
|
||||
@JvmName("sendMessageAsync")
|
||||
open fun __sendMessageAsyncForJava__(message: Message): Future<MessageReceipt<out Contact>> {
|
||||
open fun __sendMessageAsyncForJava__(message: Message): Future<MessageReceipt<Contact>> {
|
||||
return future { sendMessage(message) }
|
||||
}
|
||||
|
||||
@ -149,7 +149,7 @@ actual abstract class ContactJavaFriendlyAPI {
|
||||
* @see Contact.sendMessage
|
||||
*/
|
||||
@JvmName("sendMessageAsync")
|
||||
open fun __sendMessageAsyncForJava__(message: String): Future<MessageReceipt<out Contact>> {
|
||||
open fun __sendMessageAsyncForJava__(message: String): Future<MessageReceipt<Contact>> {
|
||||
return future { sendMessage(message) }
|
||||
}
|
||||
|
||||
|
@ -90,7 +90,7 @@ actual abstract class QQ : Contact(), CoroutineScope {
|
||||
* @return 消息回执. 可进行撤回 ([MessageReceipt.recall])
|
||||
*/
|
||||
@JvmSynthetic
|
||||
actual abstract override suspend fun sendMessage(message: Message): MessageReceipt<out QQ>
|
||||
actual abstract override suspend fun sendMessage(message: Message): MessageReceipt<QQ>
|
||||
|
||||
/**
|
||||
* 上传一个图片以备发送.
|
||||
|
@ -32,8 +32,13 @@ import java.net.URL
|
||||
* 一条从服务器接收到的消息事件.
|
||||
* JVM 平台相关扩展
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
|
||||
actual abstract class MessagePacket<TSender : QQ, TSubject : Contact> actual constructor() : MessagePacketBase<TSender, TSubject>() {
|
||||
actual sealed class MessagePacket<TSender : QQ, TSubject : Contact> actual constructor() : MessagePacketBase<TSender, TSubject>() {
|
||||
// region 上传图片
|
||||
suspend inline fun uploadImage(image: BufferedImage): Image = subject.uploadImage(image)
|
||||
|
||||
|
@ -29,7 +29,7 @@ import net.mamoe.mirai.utils.unsafeWeakRef
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
@OptIn(MiraiInternalAPI::class)
|
||||
actual open class MessageReceipt<C : Contact> @OptIn(ExperimentalMessageSource::class)
|
||||
actual open class MessageReceipt<out C : Contact> @OptIn(ExperimentalMessageSource::class)
|
||||
actual constructor(
|
||||
actual val source: MessageSource,
|
||||
target: C,
|
||||
|
Loading…
Reference in New Issue
Block a user