mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-04 15:56:57 +08:00
Fix ambiguous message event names. Fix #299.
Binary compatibility until 1.2.0. Migrations: - `MessagePacket` deprecated in favor of `MessageEvent` - `MessagePacketBase` deprecated in favor of `MessageEvent` - `ContactMessage` -> `MessageEvent` - `FriendMessage` -> `FriendMessageEvent` - `GroupMessage` -> `GroupMessageEvent` - `TempMessage` -> `TempMessageEvent`
This commit is contained in:
parent
66da881ebb
commit
4ee27f2069
@ -59,17 +59,17 @@ internal fun Contact.logMessageSent(message: Message) {
|
||||
}
|
||||
|
||||
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
|
||||
internal fun ContactMessage.logMessageReceived() {
|
||||
internal fun MessageEvent.logMessageReceived() {
|
||||
when (this) {
|
||||
is GroupMessage -> bot.logger.verbose {
|
||||
is GroupMessageEvent -> bot.logger.verbose {
|
||||
"[${group.name.singleLine()}(${group.id})] ${senderName.singleLine()}(${sender.id}) -> ${message.toString()
|
||||
.singleLine()}"
|
||||
}
|
||||
is TempMessage -> bot.logger.verbose {
|
||||
is TempMessageEvent -> bot.logger.verbose {
|
||||
"[${group.name.singleLine()}(${group.id})] ${senderName.singleLine()}(Temp ${sender.id}) -> ${message.toString()
|
||||
.singleLine()}"
|
||||
}
|
||||
is FriendMessage -> bot.logger.verbose {
|
||||
is FriendMessageEvent -> bot.logger.verbose {
|
||||
"${sender.nick.singleLine()}(${sender.id}) -> ${message.toString().singleLine()}"
|
||||
}
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ import kotlinx.io.core.use
|
||||
import net.mamoe.mirai.event.*
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.event.events.BotOnlineEvent
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.network.BotNetworkHandler
|
||||
import net.mamoe.mirai.network.UnsupportedSMSLoginException
|
||||
import net.mamoe.mirai.network.WrongPasswordException
|
||||
@ -495,7 +495,7 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
||||
is Packet.NoLog -> {
|
||||
// nothing to do
|
||||
}
|
||||
is ContactMessage -> packet.logMessageReceived()
|
||||
is MessageEvent -> packet.logMessageReceived()
|
||||
is Event -> bot.logger.verbose { "Event: ${packet.toString().singleLine()}" }
|
||||
else -> logger.verbose { "Packet: ${packet.toString().singleLine()}" }
|
||||
}
|
||||
|
@ -29,8 +29,8 @@ import net.mamoe.mirai.event.events.BotJoinGroupEvent
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.event.events.MemberJoinEvent
|
||||
import net.mamoe.mirai.getFriendOrNull
|
||||
import net.mamoe.mirai.message.FriendMessage
|
||||
import net.mamoe.mirai.message.TempMessage
|
||||
import net.mamoe.mirai.message.FriendMessageEvent
|
||||
import net.mamoe.mirai.message.TempMessageEvent
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.contact.GroupImpl
|
||||
@ -274,7 +274,7 @@ internal class MessageSvc {
|
||||
friend.lastMessageSequence.loop { instant ->
|
||||
if (msg.msgHead.msgSeq > instant) {
|
||||
if (friend.lastMessageSequence.compareAndSet(instant, msg.msgHead.msgSeq)) {
|
||||
return@mapNotNull FriendMessage(
|
||||
return@mapNotNull FriendMessageEvent(
|
||||
friend,
|
||||
msg.toMessageChain(bot, groupIdOrZero = 0, onlineSource = true),
|
||||
msg.msgHead.msgTime
|
||||
@ -297,7 +297,7 @@ internal class MessageSvc {
|
||||
member.lastMessageSequence.loop { instant ->
|
||||
if (msg.msgHead.msgSeq > instant) {
|
||||
if (member.lastMessageSequence.compareAndSet(instant, msg.msgHead.msgSeq)) {
|
||||
return@mapNotNull TempMessage(
|
||||
return@mapNotNull TempMessageEvent(
|
||||
member,
|
||||
msg.toMessageChain(
|
||||
bot,
|
||||
|
@ -23,7 +23,7 @@ import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.*
|
||||
import net.mamoe.mirai.getFriendOrNull
|
||||
import net.mamoe.mirai.getGroupOrNull
|
||||
import net.mamoe.mirai.message.GroupMessage
|
||||
import net.mamoe.mirai.message.GroupMessageEvent
|
||||
import net.mamoe.mirai.qqandroid.QQAndroidBot
|
||||
import net.mamoe.mirai.qqandroid.contact.*
|
||||
import net.mamoe.mirai.qqandroid.message.contextualBugReportException
|
||||
@ -109,7 +109,7 @@ internal class OnlinePush {
|
||||
}
|
||||
|
||||
val flags = extraInfo?.flags ?: 0
|
||||
return GroupMessage(
|
||||
return GroupMessageEvent(
|
||||
senderName = name.also {
|
||||
if (it != sender.nameCard) {
|
||||
val origin = sender._nameCard
|
||||
|
@ -16,7 +16,7 @@ import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.event.events.EventCancelledException
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.FriendMessageSendEvent
|
||||
import net.mamoe.mirai.event.events.MessageSendEvent.GroupMessageSendEvent
|
||||
import net.mamoe.mirai.message.FriendMessage
|
||||
import net.mamoe.mirai.message.FriendMessageEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.toMessage
|
||||
@ -29,7 +29,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
* 对于同一个 [Bot], 任何一个人的 [Friend] 实例都是单一的.
|
||||
* [Friend] 无法通过任何方式直接构造. 任何时候都应从 [Bot.getFriend] 或事件中获取.
|
||||
*
|
||||
* @see FriendMessage
|
||||
* @see FriendMessageEvent
|
||||
*/
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
abstract class Friend : User(), CoroutineScope {
|
||||
|
@ -17,10 +17,10 @@ package net.mamoe.mirai.event
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.internal.*
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.FriendMessage
|
||||
import net.mamoe.mirai.message.GroupMessage
|
||||
import net.mamoe.mirai.message.TempMessage
|
||||
import net.mamoe.mirai.message.FriendMessageEvent
|
||||
import net.mamoe.mirai.message.GroupMessageEvent
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.message.TempMessageEvent
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmOverloads
|
||||
@ -31,7 +31,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
* 消息事件的处理器.
|
||||
*
|
||||
* 注:
|
||||
* 接受者 T 为 [ContactMessage]
|
||||
* 接受者 T 为 [MessageEvent]
|
||||
* 参数 String 为 转为字符串了的消息 ([Message.toString])
|
||||
*/
|
||||
typealias MessageListener<T, R> = @MessageDsl suspend T.(String) -> R
|
||||
@ -47,7 +47,7 @@ typealias MessageListener<T, R> = @MessageDsl suspend T.(String) -> R
|
||||
* @see subscribeFriendMessages
|
||||
*/
|
||||
@MessageDsl
|
||||
open class MessageSubscribersBuilder<M : ContactMessage, out Ret, R : RR, RR>(
|
||||
open class MessageSubscribersBuilder<M : MessageEvent, out Ret, R : RR, RR>(
|
||||
/**
|
||||
* 用于 [MessageListener] 无返回值的替代.
|
||||
*/
|
||||
@ -231,7 +231,7 @@ open class MessageSubscribersBuilder<M : ContactMessage, out Ret, R : RR, RR>(
|
||||
|
||||
/** 如果是这个人发的消息. 消息目前只会是群消息 */
|
||||
@MessageDsl
|
||||
fun sentBy(name: String): ListeningFilter = content { this is GroupMessage && this.senderName == name }
|
||||
fun sentBy(name: String): ListeningFilter = content { this is GroupMessageEvent && this.senderName == name }
|
||||
|
||||
/** 如果是这个人发的消息. 消息可以是好友消息也可以是群消息 */
|
||||
@MessageDsl
|
||||
@ -247,36 +247,37 @@ open class MessageSubscribersBuilder<M : ContactMessage, out Ret, R : RR, RR>(
|
||||
|
||||
/** 如果是好友发来的消息 */
|
||||
@MessageDsl
|
||||
fun sentByFriend(onEvent: MessageListener<FriendMessage, R>): Ret =
|
||||
content({ this is FriendMessage }) { onEvent(this as FriendMessage, it) }
|
||||
fun sentByFriend(onEvent: MessageListener<FriendMessageEvent, R>): Ret =
|
||||
content({ this is FriendMessageEvent }) { onEvent(this as FriendMessageEvent, it) }
|
||||
|
||||
/** 如果是好友发来的消息 */
|
||||
@MessageDsl
|
||||
fun sentByFriend(): ListeningFilter = newListeningFilter { this is FriendMessage }
|
||||
fun sentByFriend(): ListeningFilter = newListeningFilter { this is FriendMessageEvent }
|
||||
|
||||
/** 如果是好友发来的消息 */
|
||||
/** 如果是群临时会话消息 */
|
||||
@MessageDsl
|
||||
fun sentByTemp(): ListeningFilter = newListeningFilter { this is TempMessage }
|
||||
fun sentByTemp(): ListeningFilter = newListeningFilter { this is TempMessageEvent }
|
||||
|
||||
/** 如果是管理员或群主发的消息 */
|
||||
@MessageDsl
|
||||
fun sentByOperator(): ListeningFilter = content { this is GroupMessage && sender.permission.isOperator() }
|
||||
fun sentByOperator(): ListeningFilter = content { this is GroupMessageEvent && sender.permission.isOperator() }
|
||||
|
||||
/** 如果是管理员发的消息 */
|
||||
@MessageDsl
|
||||
fun sentByAdministrator(): ListeningFilter = content { this is GroupMessage && sender.permission.isAdministrator() }
|
||||
fun sentByAdministrator(): ListeningFilter =
|
||||
content { this is GroupMessageEvent && sender.permission.isAdministrator() }
|
||||
|
||||
/** 如果是群主发的消息 */
|
||||
@MessageDsl
|
||||
fun sentByOwner(): ListeningFilter = content { this is GroupMessage && sender.isOwner() }
|
||||
fun sentByOwner(): ListeningFilter = content { this is GroupMessageEvent && sender.isOwner() }
|
||||
|
||||
/** 如果是来自这个群的消息 */
|
||||
@MessageDsl
|
||||
fun sentFrom(groupId: Long): ListeningFilter = content { this is GroupMessage && group.id == groupId }
|
||||
fun sentFrom(groupId: Long): ListeningFilter = content { this is GroupMessageEvent && group.id == groupId }
|
||||
|
||||
/** 如果是来自这个群的消息 */
|
||||
@MessageDsl
|
||||
fun sentFrom(group: Group): ListeningFilter = content { this is GroupMessage && group.id == group.id }
|
||||
fun sentFrom(group: Group): ListeningFilter = content { this is GroupMessageEvent && group.id == group.id }
|
||||
|
||||
/** [消息内容][Message.contentToString]包含目标为 [Bot] 的 [At] */
|
||||
@MessageDsl
|
||||
|
@ -12,7 +12,7 @@ package net.mamoe.mirai.event.internal
|
||||
import net.mamoe.mirai.event.MessageDsl
|
||||
import net.mamoe.mirai.event.MessageListener
|
||||
import net.mamoe.mirai.event.MessageSubscribersBuilder
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
|
||||
|
||||
/*
|
||||
@ -20,13 +20,13 @@ import net.mamoe.mirai.message.ContactMessage
|
||||
*/
|
||||
|
||||
@MessageDsl
|
||||
internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.content(
|
||||
internal fun <M : MessageEvent, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.content(
|
||||
filter: M.(String) -> Boolean,
|
||||
onEvent: MessageListener<M, RR>
|
||||
): Ret =
|
||||
subscriber(filter) { onEvent(this, it) }
|
||||
|
||||
internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.endsWithImpl(
|
||||
internal fun <M : MessageEvent, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.endsWithImpl(
|
||||
suffix: String,
|
||||
removeSuffix: Boolean = true,
|
||||
trim: Boolean = true,
|
||||
@ -46,7 +46,7 @@ internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M,
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.startsWithImpl(
|
||||
internal fun <M : MessageEvent, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.startsWithImpl(
|
||||
prefix: String,
|
||||
removePrefix: Boolean = true,
|
||||
trim: Boolean = true,
|
||||
@ -64,7 +64,7 @@ internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M,
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.containsAllImpl(
|
||||
internal fun <M : MessageEvent, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.containsAllImpl(
|
||||
sub: Array<out String>,
|
||||
ignoreCase: Boolean = false,
|
||||
trim: Boolean = true
|
||||
@ -76,7 +76,7 @@ internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M,
|
||||
content { sub.all { toCheck -> it.contains(toCheck, ignoreCase = ignoreCase) } }
|
||||
}
|
||||
|
||||
internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.containsAnyImpl(
|
||||
internal fun <M : MessageEvent, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.containsAnyImpl(
|
||||
vararg sub: String,
|
||||
ignoreCase: Boolean = false,
|
||||
trim: Boolean = true
|
||||
@ -86,7 +86,7 @@ internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M,
|
||||
content { list.any { toCheck -> it.contains(toCheck, ignoreCase = ignoreCase) } }
|
||||
} else content { sub.any { toCheck -> it.contains(toCheck, ignoreCase = ignoreCase) } }
|
||||
|
||||
internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.caseImpl(
|
||||
internal fun <M : MessageEvent, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.caseImpl(
|
||||
equals: String,
|
||||
ignoreCase: Boolean = false,
|
||||
trim: Boolean = true
|
||||
@ -99,7 +99,7 @@ internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M,
|
||||
}
|
||||
}
|
||||
|
||||
internal fun <M : ContactMessage, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.containsImpl(
|
||||
internal fun <M : MessageEvent, Ret, R : RR, RR> MessageSubscribersBuilder<M, Ret, R, RR>.containsImpl(
|
||||
sub: String,
|
||||
ignoreCase: Boolean = false,
|
||||
trim: Boolean = true,
|
||||
|
@ -12,7 +12,7 @@
|
||||
package net.mamoe.mirai.event
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
import net.mamoe.mirai.message.isContextIdenticalWith
|
||||
@ -61,7 +61,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
*/
|
||||
@SinceMirai("0.29.0")
|
||||
@Suppress("unused")
|
||||
suspend inline fun <reified T : ContactMessage> T.whileSelectMessages(
|
||||
suspend inline fun <reified T : MessageEvent> T.whileSelectMessages(
|
||||
timeoutMillis: Long = -1,
|
||||
filterContext: Boolean = true,
|
||||
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
|
||||
@ -74,7 +74,7 @@ suspend inline fun <reified T : ContactMessage> T.whileSelectMessages(
|
||||
@MiraiExperimentalAPI
|
||||
@SinceMirai("0.29.0")
|
||||
@JvmName("selectMessages1")
|
||||
suspend inline fun <reified T : ContactMessage> T.selectMessagesUnit(
|
||||
suspend inline fun <reified T : MessageEvent> T.selectMessagesUnit(
|
||||
timeoutMillis: Long = -1,
|
||||
filterContext: Boolean = true,
|
||||
crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, Unit>.() -> Unit
|
||||
@ -104,7 +104,7 @@ suspend inline fun <reified T : ContactMessage> T.selectMessagesUnit(
|
||||
@SinceMirai("0.29.0")
|
||||
@Suppress("unused") // false positive
|
||||
// @BuilderInference // https://youtrack.jetbrains.com/issue/KT-37716
|
||||
suspend inline fun <reified T : ContactMessage, R> T.selectMessages(
|
||||
suspend inline fun <reified T : MessageEvent, R> T.selectMessages(
|
||||
timeoutMillis: Long = -1,
|
||||
filterContext: Boolean = true,
|
||||
// @BuilderInference
|
||||
@ -121,7 +121,7 @@ suspend inline fun <reified T : ContactMessage, R> T.selectMessages(
|
||||
*/
|
||||
@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE")
|
||||
@SinceMirai("0.29.0")
|
||||
abstract class MessageSelectBuilder<M : ContactMessage, R> @PublishedApi internal constructor(
|
||||
abstract class MessageSelectBuilder<M : MessageEvent, R> @PublishedApi internal constructor(
|
||||
ownerMessagePacket: M,
|
||||
stub: Any?,
|
||||
subscriber: (M.(String) -> Boolean, MessageListener<M, Any?>) -> Unit
|
||||
@ -236,7 +236,7 @@ abstract class MessageSelectBuilder<M : ContactMessage, R> @PublishedApi interna
|
||||
* @see MessageSubscribersBuilder 查看上层 API
|
||||
*/
|
||||
@SinceMirai("0.29.0")
|
||||
abstract class MessageSelectBuilderUnit<M : ContactMessage, R> @PublishedApi internal constructor(
|
||||
abstract class MessageSelectBuilderUnit<M : MessageEvent, R> @PublishedApi internal constructor(
|
||||
private val ownerMessagePacket: M,
|
||||
stub: Any?,
|
||||
subscriber: (M.(String) -> Boolean, MessageListener<M, Any?>) -> Unit
|
||||
@ -480,7 +480,7 @@ internal val ExceptionHandlerIgnoringCancellationException = CoroutineExceptionH
|
||||
@PublishedApi
|
||||
@BuilderInference
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
internal suspend inline fun <reified T : ContactMessage, R> T.selectMessagesImpl(
|
||||
internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
|
||||
timeoutMillis: Long = -1,
|
||||
isUnit: Boolean,
|
||||
filterContext: Boolean = true,
|
||||
@ -579,7 +579,7 @@ internal suspend inline fun <reified T : ContactMessage, R> T.selectMessagesImpl
|
||||
|
||||
@Suppress("unused")
|
||||
@PublishedApi
|
||||
internal suspend inline fun <reified T : ContactMessage> T.whileSelectMessagesImpl(
|
||||
internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl(
|
||||
timeoutMillis: Long = -1,
|
||||
filterContext: Boolean = true,
|
||||
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
|
||||
|
@ -17,10 +17,10 @@ import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.channels.ReceiveChannel
|
||||
import net.mamoe.mirai.Bot
|
||||
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.TempMessage
|
||||
import net.mamoe.mirai.message.FriendMessageEvent
|
||||
import net.mamoe.mirai.message.GroupMessageEvent
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.message.TempMessageEvent
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.InvocationKind
|
||||
@ -28,7 +28,7 @@ import kotlin.contracts.contract
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder<ContactMessage, Listener<ContactMessage>, Unit, Unit>
|
||||
typealias MessagePacketSubscribersBuilder = MessageSubscribersBuilder<MessageEvent, Listener<MessageEvent>, Unit, Unit>
|
||||
|
||||
/**
|
||||
* 订阅来自所有 [Bot] 的所有联系人的消息事件. 联系人可以是任意群或任意好友或临时会话.
|
||||
@ -47,7 +47,7 @@ fun <R> CoroutineScope.subscribeMessages(
|
||||
}
|
||||
|
||||
return MessagePacketSubscribersBuilder(Unit)
|
||||
{ filter, messageListener: MessageListener<ContactMessage, Unit> ->
|
||||
{ filter, messageListener: MessageListener<MessageEvent, Unit> ->
|
||||
// subscribeAlways 即注册一个监听器. 这个监听器收到消息后就传递给 [messageListener]
|
||||
// messageListener 即为 DSL 里 `contains(...) { }`, `startsWith(...) { }` 的代码块.
|
||||
subscribeAlways(coroutineContext, concurrencyKind) {
|
||||
@ -59,7 +59,7 @@ fun <R> CoroutineScope.subscribeMessages(
|
||||
}.run(listeners)
|
||||
}
|
||||
|
||||
typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<GroupMessage, Listener<GroupMessage>, Unit, Unit>
|
||||
typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<GroupMessageEvent, Listener<GroupMessageEvent>, Unit, Unit>
|
||||
|
||||
/**
|
||||
* 订阅来自所有 [Bot] 的所有群消息事件
|
||||
@ -84,7 +84,7 @@ fun <R> CoroutineScope.subscribeGroupMessages(
|
||||
}.run(listeners)
|
||||
}
|
||||
|
||||
typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<FriendMessage, Listener<FriendMessage>, Unit, Unit>
|
||||
typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<FriendMessageEvent, Listener<FriendMessageEvent>, Unit, Unit>
|
||||
|
||||
/**
|
||||
* 订阅来自所有 [Bot] 的所有好友消息事件
|
||||
@ -109,7 +109,7 @@ fun <R> CoroutineScope.subscribeFriendMessages(
|
||||
}.run(listeners)
|
||||
}
|
||||
|
||||
typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder<TempMessage, Listener<TempMessage>, Unit, Unit>
|
||||
typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder<TempMessageEvent, Listener<TempMessageEvent>, Unit, Unit>
|
||||
|
||||
/**
|
||||
* 订阅来自所有 [Bot] 的所有临时会话消息事件
|
||||
|
@ -1,383 +0,0 @@
|
||||
/*
|
||||
* 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(
|
||||
"EXPERIMENTAL_UNSIGNED_LITERALS",
|
||||
"EXPERIMENTAL_API_USAGE",
|
||||
"unused",
|
||||
"INVISIBLE_REFERENCE",
|
||||
"INVISIBLE_MEMBER"
|
||||
)
|
||||
@file:OptIn(MiraiInternalAPI::class)
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.async
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.*
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.qqandroid.network.Packet
|
||||
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]
|
||||
* - [临时会话消息事件][TempMessage]
|
||||
*
|
||||
* @see isContextIdenticalWith 判断语境是否相同
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@SinceMirai("0.32.0")
|
||||
abstract class ContactMessage : MessagePacket<User, Contact>(), BotEvent
|
||||
|
||||
/**
|
||||
* 一条从服务器接收到的消息事件.
|
||||
* 请查看各平台的 `actual` 实现的说明.
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
expect abstract class MessagePacket<TSender : User, TSubject : Contact> constructor() :
|
||||
MessagePacketBase<TSender, TSubject>
|
||||
|
||||
/**
|
||||
* 仅内部使用, 请使用 [ContactMessage]
|
||||
*/ // Tips: 在 IntelliJ 中 (左侧边栏) 打开 `Structure`, 可查看类结构
|
||||
@Deprecated(
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
||||
abstract class MessagePacketBase<out TSender : User, out TSubject : Contact> : Packet, BotEvent, AbstractEvent() {
|
||||
/**
|
||||
* 接受到这条消息的
|
||||
*/
|
||||
abstract override val bot: Bot
|
||||
|
||||
/**
|
||||
* 消息事件主体.
|
||||
*
|
||||
* - 对于好友消息, 这个属性为 [Friend] 的实例, 与 [sender] 引用相同;
|
||||
* - 对于临时会话消息, 这个属性为 [Member] 的实例, 与 [sender] 引用相同;
|
||||
* - 对于群消息, 这个属性为 [Group] 的实例, 与 [GroupMessage.group] 引用相同
|
||||
*
|
||||
* 在回复消息时, 可通过 [subject] 作为回复对象
|
||||
*/
|
||||
abstract val subject: TSubject
|
||||
|
||||
/**
|
||||
* 发送人.
|
||||
*
|
||||
* 在好友消息时为 [Friend] 的实例, 在群消息时为 [Member] 的实例
|
||||
*/
|
||||
abstract val sender: TSender
|
||||
|
||||
abstract val senderName: String
|
||||
|
||||
/**
|
||||
* 消息内容
|
||||
*/
|
||||
abstract val message: MessageChain
|
||||
|
||||
/**
|
||||
* 消息发送时间 (由服务器提供)
|
||||
*/
|
||||
@SinceMirai("0.39.0")
|
||||
abstract val time: Int
|
||||
|
||||
/**
|
||||
* 消息源
|
||||
*/
|
||||
open val source: OnlineMessageSource.Incoming get() = message.source as OnlineMessageSource.Incoming
|
||||
|
||||
// region 发送 Message
|
||||
|
||||
/**
|
||||
* 给这个消息事件的主体发送消息
|
||||
* 对于好友消息事件, 这个方法将会给好友 ([subject]) 发送消息
|
||||
* 对于群消息事件, 这个方法将会给群 ([subject]) 发送消息
|
||||
*/
|
||||
suspend inline fun reply(message: Message): MessageReceipt<TSubject> =
|
||||
subject.sendMessage(message.asMessageChain()) as MessageReceipt<TSubject>
|
||||
|
||||
suspend inline fun reply(plain: String): MessageReceipt<TSubject> =
|
||||
subject.sendMessage(plain.toMessage().asMessageChain()) as MessageReceipt<TSubject>
|
||||
// endregion
|
||||
|
||||
// region 图片
|
||||
suspend inline fun ExternalImage.upload(): Image = this.upload(subject)
|
||||
|
||||
suspend inline fun ExternalImage.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
|
||||
suspend inline fun Image.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
suspend inline fun Message.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
suspend inline fun String.send(): MessageReceipt<TSubject> = this.toMessage().sendTo(subject)
|
||||
// endregion
|
||||
|
||||
|
||||
// region 引用回复
|
||||
/**
|
||||
* 给这个消息事件的主体发送引用回复消息
|
||||
* 对于好友消息事件, 这个方法将会给好友 ([subject]) 发送消息
|
||||
* 对于群消息事件, 这个方法将会给群 ([subject]) 发送消息
|
||||
*/
|
||||
suspend inline fun quoteReply(message: MessageChain): MessageReceipt<TSubject> =
|
||||
reply(this.message.quote() + message)
|
||||
|
||||
suspend inline fun quoteReply(message: Message): MessageReceipt<TSubject> = reply(this.message.quote() + message)
|
||||
suspend inline fun quoteReply(plain: String): MessageReceipt<TSubject> = reply(this.message.quote() + plain)
|
||||
|
||||
@JvmName("reply2")
|
||||
suspend inline fun String.quoteReply(): MessageReceipt<TSubject> = quoteReply(this)
|
||||
|
||||
@JvmName("reply2")
|
||||
suspend inline fun Message.quoteReply(): MessageReceipt<TSubject> = quoteReply(this)
|
||||
|
||||
@JvmName("reply2")
|
||||
suspend inline fun MessageChain.quoteReply(): MessageReceipt<TSubject> = quoteReply(this)
|
||||
|
||||
// endregion
|
||||
|
||||
inline operator fun <M : Message> get(at: Message.Key<M>): M {
|
||||
return this.message[at]
|
||||
}
|
||||
|
||||
inline fun At.isBot(): Boolean = target == bot.id
|
||||
|
||||
// endregion
|
||||
|
||||
// region 下载图片
|
||||
|
||||
|
||||
/**
|
||||
* 获取图片下载链接
|
||||
*
|
||||
* @return "http://gchat.qpic.cn/gchatpic_new/..."
|
||||
*/
|
||||
suspend inline fun Image.url(): String = bot.queryImageUrl(this@url)
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个 [MessagePacket] 的 [MessagePacket.sender] 和 [MessagePacket.subject] 是否相同
|
||||
*/
|
||||
@SinceMirai("0.29.0")
|
||||
fun ContactMessage.isContextIdenticalWith(another: ContactMessage): Boolean {
|
||||
return this.sender == another.sender && this.subject == another.subject && this.bot == another.bot
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessagePacket.sender] 和 [MessagePacket.subject] 与 [this] 相同且通过 [筛选][filter] 的 [MessagePacket]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @param filter 过滤器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
|
||||
*
|
||||
* @see syncFromEvent
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessage(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): MessageChain {
|
||||
return syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessage) }?.takeIf { filter(it, it) }
|
||||
}.message
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessagePacket.sender] 和 [MessagePacket.subject] 与 [this] 相同且通过 [筛选][filter] 的 [MessagePacket]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @param filter 过滤器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
|
||||
* @return 消息链. 超时时返回 `null`
|
||||
*
|
||||
* @see syncFromEventOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessageOrNull(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): MessageChain? {
|
||||
return syncFromEventOrNull<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageOrNull) }?.takeIf { filter(it, it) }
|
||||
}?.message
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessagePacket.sender] 和 [MessagePacket.subject] 与 [this] 相同的 [MessagePacket]
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
*
|
||||
* @throws TimeoutCancellationException
|
||||
*
|
||||
* @see syncFromEvent
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessage(
|
||||
timeoutMillis: Long = -1
|
||||
): MessageChain {
|
||||
return syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessage) }
|
||||
}.message
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nextMessage
|
||||
* @throws TimeoutCancellationException
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : ContactMessage> P.nextMessageAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<MessageChain> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageAsync) }
|
||||
}.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nextMessage
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : ContactMessage> P.nextMessageAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): Deferred<MessageChain> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageAsync) }
|
||||
.takeIf { filter(this, this) }
|
||||
}.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessagePacket.sender] 和 [MessagePacket.subject] 与 [this] 相同的 [MessagePacket]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @return 消息链. 超时时返回 `null`
|
||||
*
|
||||
* @see syncFromEventOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : ContactMessage> P.nextMessageOrNull(
|
||||
timeoutMillis: Long = -1
|
||||
): MessageChain? {
|
||||
return syncFromEventOrNull<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageOrNull) }
|
||||
}?.message
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nextMessageOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : ContactMessage> P.nextMessageOrNullAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<MessageChain?> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEventOrNull<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageOrNullAsync) }
|
||||
}?.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessagePacket.sender] 和 [MessagePacket.subject] 与 [this] 相同的 [MessagePacket]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
*
|
||||
* @see syncFromEvent
|
||||
* @see whileSelectMessages
|
||||
* @see selectMessages
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified M : Message> ContactMessage.nextMessageContaining(
|
||||
timeoutMillis: Long = -1
|
||||
): M {
|
||||
return syncFromEvent<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContaining) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}.message.firstIsInstance()
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
inline fun <reified M : Message> ContactMessage.nextMessageContainingAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<M> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
syncFromEvent<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingAsync) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}.message.firstIsInstance<M>()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessagePacket.sender] 和 [MessagePacket.subject] 与 [this] 相同并含有 [M] 类型的消息的 [MessagePacket]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @return 指定类型的消息. 超时时返回 `null`
|
||||
*
|
||||
* @see syncFromEventOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified M : Message> ContactMessage.nextMessageContainingOrNull(
|
||||
timeoutMillis: Long = -1
|
||||
): M? {
|
||||
return syncFromEventOrNull<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingOrNull) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}?.message?.firstIsInstance()
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
inline fun <reified M : Message> ContactMessage.nextMessageContainingOrNullAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<M?> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEventOrNull<ContactMessage, ContactMessage>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingOrNullAsync) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}?.message?.firstIsInstance<M>()
|
||||
}
|
||||
}
|
@ -18,17 +18,21 @@ import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.MessageSource
|
||||
import net.mamoe.mirai.message.data.OnlineMessageSource
|
||||
import net.mamoe.mirai.message.data.source
|
||||
import net.mamoe.mirai.utils.PlannedRemoval
|
||||
|
||||
/**
|
||||
* 好友消息事件
|
||||
* 机器人收到的好友消息的事件
|
||||
*
|
||||
* @see MessageEvent
|
||||
*/
|
||||
class FriendMessage constructor(
|
||||
class FriendMessageEvent constructor(
|
||||
override val sender: Friend,
|
||||
override val message: MessageChain,
|
||||
override val time: Int
|
||||
) : ContactMessage(), BroadcastControllable {
|
||||
) : @PlannedRemoval("1.2.0") FriendMessage(), BroadcastControllable {
|
||||
init {
|
||||
val source = message.getOrNull(MessageSource) ?: error("Cannot find MessageSource from message")
|
||||
val source =
|
||||
message.getOrNull(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" }
|
||||
}
|
||||
|
||||
@ -37,5 +41,5 @@ class FriendMessage constructor(
|
||||
override val senderName: String get() = sender.nick
|
||||
override val source: OnlineMessageSource.Incoming.FromFriend get() = message.source as OnlineMessageSource.Incoming.FromFriend
|
||||
|
||||
override fun toString(): String = "FriendMessage(sender=${sender.id}, message=$message)"
|
||||
override fun toString(): String = "FriendMessageEvent(sender=${sender.id}, message=$message)"
|
||||
}
|
@ -7,6 +7,8 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("DEPRECATION_ERROR", "unused", "NOTHING_TO_INLINE")
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
@ -15,14 +17,14 @@ import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.contact.MemberPermission
|
||||
import net.mamoe.mirai.event.Event
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.utils.PlannedRemoval
|
||||
|
||||
/**
|
||||
* 群消息事件
|
||||
* 机器人收到的群消息的事件
|
||||
*
|
||||
* @see ContactMessage
|
||||
* @see MessageEvent
|
||||
*/
|
||||
@Suppress("unused", "NOTHING_TO_INLINE")
|
||||
class GroupMessage(
|
||||
class GroupMessageEvent(
|
||||
override val senderName: String,
|
||||
/**
|
||||
* 发送方权限.
|
||||
@ -31,13 +33,13 @@ class GroupMessage(
|
||||
override val sender: Member,
|
||||
override val message: MessageChain,
|
||||
override val time: Int
|
||||
) : ContactMessage(), Event {
|
||||
) : @PlannedRemoval("1.2.0") GroupMessage(), Event {
|
||||
init {
|
||||
val source = message.getOrNull(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" }
|
||||
}
|
||||
|
||||
val group: Group get() = sender.group
|
||||
inline val group: Group get() = sender.group
|
||||
override val bot: Bot get() = sender.bot
|
||||
|
||||
override val subject: Group get() = group
|
||||
@ -47,5 +49,5 @@ class GroupMessage(
|
||||
inline fun At.asMember(): Member = group[this.target]
|
||||
|
||||
override fun toString(): String =
|
||||
"GroupMessage(group=${group.id}, senderName=$senderName, sender=${sender.id}, permission=${permission.name}, message=$message)"
|
||||
"GroupMessageEvent(group=${group.id}, senderName=$senderName, sender=${sender.id}, permission=${permission.name}, message=$message)"
|
||||
}
|
@ -0,0 +1,221 @@
|
||||
/*
|
||||
* 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(
|
||||
"EXPERIMENTAL_UNSIGNED_LITERALS",
|
||||
"EXPERIMENTAL_API_USAGE",
|
||||
"unused",
|
||||
"DECLARATION_CANT_BE_INLINED", "UNCHECKED_CAST", "NOTHING_TO_INLINE"
|
||||
)
|
||||
|
||||
@file:OptIn(MiraiInternalAPI::class)
|
||||
@file:JvmMultifileClass
|
||||
@file:JvmName("MessageEventKt")
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.AbstractEvent
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.message.data.*
|
||||
import net.mamoe.mirai.qqandroid.network.Packet
|
||||
import net.mamoe.mirai.utils.*
|
||||
import kotlin.jvm.JvmMultifileClass
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
/**
|
||||
* 一个 (收到的) 消息事件.
|
||||
*
|
||||
* 它是一个 [BotEvent], 因此可以被 [监听][Bot.subscribe]
|
||||
*
|
||||
* 支持的消息类型:
|
||||
* - [群消息事件][GroupMessageEvent]
|
||||
* - [好友消息事件][FriendMessageEvent]
|
||||
* - [临时会话消息事件][TempMessageEvent]
|
||||
*
|
||||
* @see isContextIdenticalWith 判断语境是否相同
|
||||
*/
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
@SinceMirai("0.32.0")
|
||||
abstract class MessageEvent : @PlannedRemoval("1.2.0") ContactMessage(),
|
||||
BotEvent, MessageEventExtensions<User, Contact> {
|
||||
|
||||
/**
|
||||
* 与这个消息事件相关的 [Bot]
|
||||
*/
|
||||
abstract override val bot: Bot
|
||||
|
||||
/**
|
||||
* 消息事件主体.
|
||||
*
|
||||
* - 对于好友消息, 这个属性为 [Friend] 的实例, 与 [sender] 引用相同;
|
||||
* - 对于临时会话消息, 这个属性为 [Member] 的实例, 与 [sender] 引用相同;
|
||||
* - 对于群消息, 这个属性为 [Group] 的实例, 与 [GroupMessageEvent.group] 引用相同
|
||||
*
|
||||
* 在回复消息时, 可通过 [subject] 作为回复对象
|
||||
*/
|
||||
abstract override val subject: Contact
|
||||
|
||||
/**
|
||||
* 发送人.
|
||||
*
|
||||
* 在好友消息时为 [Friend] 的实例, 在群消息时为 [Member] 的实例
|
||||
*/
|
||||
abstract override val sender: User
|
||||
|
||||
abstract val senderName: String
|
||||
|
||||
/** 消息内容 */
|
||||
abstract override val message: MessageChain
|
||||
|
||||
/** 消息发送时间 (由服务器提供) */
|
||||
@SinceMirai("0.39.0")
|
||||
abstract val time: Int
|
||||
|
||||
/** 消息源 */
|
||||
open val source: OnlineMessageSource.Incoming get() = message.source as OnlineMessageSource.Incoming
|
||||
}
|
||||
|
||||
/** 消息事件的扩展函数 */
|
||||
@Suppress("EXPOSED_SUPER_INTERFACE") // Functions are visible
|
||||
interface MessageEventExtensions<out TSender : User, out TSubject : Contact> :
|
||||
MessageEventPlatformExtensions<TSender, TSubject> {
|
||||
|
||||
// region 发送 Message
|
||||
|
||||
/**
|
||||
* 给这个消息事件的主体发送消息
|
||||
* 对于好友消息事件, 这个方法将会给好友 ([subject]) 发送消息
|
||||
* 对于群消息事件, 这个方法将会给群 ([subject]) 发送消息
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun reply(message: Message): MessageReceipt<TSubject> =
|
||||
subject.sendMessage(message.asMessageChain()) as MessageReceipt<TSubject>
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun reply(plain: String): MessageReceipt<TSubject> =
|
||||
subject.sendMessage(plain.toMessage().asMessageChain()) as MessageReceipt<TSubject>
|
||||
|
||||
// endregion
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun ExternalImage.upload(): Image = this.upload(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun ExternalImage.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun Image.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun Message.send(): MessageReceipt<TSubject> = this.sendTo(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun String.send(): MessageReceipt<TSubject> = this.toMessage().sendTo(subject)
|
||||
|
||||
// region 引用回复
|
||||
/**
|
||||
* 给这个消息事件的主体发送引用回复消息
|
||||
* 对于好友消息事件, 这个方法将会给好友 ([subject]) 发送消息
|
||||
* 对于群消息事件, 这个方法将会给群 ([subject]) 发送消息
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun quoteReply(message: MessageChain): MessageReceipt<TSubject> =
|
||||
reply(this.message.quote() + message)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun quoteReply(message: Message): MessageReceipt<TSubject> = reply(this.message.quote() + message)
|
||||
|
||||
@JvmSynthetic
|
||||
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
|
||||
inline fun At.isBot(): Boolean = target == bot.id
|
||||
|
||||
|
||||
/**
|
||||
* 获取图片下载链接
|
||||
* @return "http://gchat.qpic.cn/gchatpic_new/..."
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun Image.url(): String = bot.queryImageUrl(this@url)
|
||||
}
|
||||
|
||||
/** 一个消息事件在各平台的相关扩展. 请使用 [MessageEventExtensions] */
|
||||
internal expect interface MessageEventPlatformExtensions<out TSender : User, out TSubject : Contact> {
|
||||
val subject: TSubject
|
||||
val sender: TSender
|
||||
val message: MessageChain
|
||||
val bot: Bot
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 已废弃, 请使用 [MessageEvent]
|
||||
*/
|
||||
@PlannedRemoval("1.2.0")
|
||||
@Deprecated(
|
||||
message = "use MessageEvent",
|
||||
replaceWith = ReplaceWith("MessageEvent", "net.mamoe.mirai.message.MessageEvent"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
abstract class MessagePacketBase<out TSender : User, out TSubject : Contact> : Packet, BotEvent, AbstractEvent()
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@Deprecated(
|
||||
message = "Ambiguous name. Use MessageEvent instead",
|
||||
replaceWith = ReplaceWith("MessageEvent", "net.mamoe.mirai.message.MessageEvent"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
abstract class MessagePacket : MessagePacketBase<User, Contact>(),
|
||||
BotEvent, MessageEventExtensions<User, Contact>
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@Deprecated(
|
||||
message = "Ambiguous name. Use MessageEvent instead",
|
||||
replaceWith = ReplaceWith("MessageEvent", "net.mamoe.mirai.message.MessageEvent"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
abstract class ContactMessage : MessagePacket(),
|
||||
BotEvent, MessageEventExtensions<User, Contact>
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@Deprecated(
|
||||
message = "Ambiguous name. Use FriendMessageEvent instead",
|
||||
replaceWith = ReplaceWith("FriendMessageEvent", "net.mamoe.mirai.message.FriendMessageEvent"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
abstract class FriendMessage : MessageEvent()
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@Deprecated(
|
||||
message = "Ambiguous name. Use GroupMessageEvent instead",
|
||||
replaceWith = ReplaceWith("GroupMessageEvent", "net.mamoe.mirai.message.GroupMessageEvent"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
abstract class GroupMessage : MessageEvent()
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@Deprecated(
|
||||
message = "Ambiguous name. Use TempMessageEvent instead",
|
||||
replaceWith = ReplaceWith("TempMessageEvent", "net.mamoe.mirai.message.TempMessageEvent"),
|
||||
level = DeprecationLevel.ERROR
|
||||
)
|
||||
abstract class TempMessage : MessageEvent()
|
@ -1,3 +1,5 @@
|
||||
@file:Suppress("DEPRECATION_ERROR", "unused", "NOTHING_TO_INLINE")
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
@ -12,14 +14,16 @@ import net.mamoe.mirai.message.data.source
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
|
||||
/**
|
||||
* 临时会话消息
|
||||
* 机器人收到的群临时会话消息的事件
|
||||
*
|
||||
* @see MessageEvent
|
||||
*/
|
||||
@SinceMirai("0.35.0")
|
||||
class TempMessage(
|
||||
class TempMessageEvent(
|
||||
override val sender: Member,
|
||||
override val message: MessageChain,
|
||||
override val time: Int
|
||||
) : ContactMessage(), BroadcastControllable {
|
||||
) : TempMessage(), BroadcastControllable {
|
||||
init {
|
||||
val source = message.getOrNull(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" }
|
||||
@ -32,5 +36,5 @@ class TempMessage(
|
||||
override val source: OnlineMessageSource.Incoming.FromTemp get() = message.source as OnlineMessageSource.Incoming.FromTemp
|
||||
|
||||
override fun toString(): String =
|
||||
"TempMessage(sender=${sender.id} from group(${sender.group.id}), message=$message)"
|
||||
"TempMessageEvent(sender=${sender.id} from group(${sender.group.id}), message=$message)"
|
||||
}
|
@ -12,8 +12,11 @@
|
||||
package net.mamoe.mirai.message.data
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.User
|
||||
import net.mamoe.mirai.contact.nameCardOrNick
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.message.data.ForwardMessage.DisplayStrategy
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.SinceMirai
|
||||
@ -72,7 +75,7 @@ import kotlin.jvm.JvmSynthetic
|
||||
*
|
||||
* ### 构造
|
||||
* - 使用 [DSL][buildForwardMessage]
|
||||
* - 通过 [ContactMessage] 集合转换: [toForwardMessage]
|
||||
* - 通过 [MessageEvent] 集合转换: [toForwardMessage]
|
||||
*
|
||||
* @see buildForwardMessage
|
||||
*/
|
||||
@ -186,7 +189,7 @@ class ForwardMessage @JvmOverloads constructor(
|
||||
*/
|
||||
@SinceMirai("0.39.0")
|
||||
@JvmOverloads
|
||||
fun Iterable<ContactMessage>.toForwardMessage(displayStrategy: DisplayStrategy = DisplayStrategy): ForwardMessage {
|
||||
fun Iterable<MessageEvent>.toForwardMessage(displayStrategy: DisplayStrategy = DisplayStrategy): ForwardMessage {
|
||||
val iterator = this.iterator()
|
||||
if (!iterator.hasNext()) return ForwardMessage(emptyList(), displayStrategy)
|
||||
return ForwardMessage(
|
||||
@ -236,7 +239,7 @@ inline fun buildForwardMessage(
|
||||
*/
|
||||
@SinceMirai("0.39.0")
|
||||
@JvmSynthetic
|
||||
inline fun ContactMessage.buildForwardMessage(
|
||||
inline fun MessageEvent.buildForwardMessage(
|
||||
context: Contact = this.subject,
|
||||
displayStrategy: DisplayStrategy = DisplayStrategy,
|
||||
block: ForwardMessageBuilder.() -> Unit
|
||||
|
@ -16,7 +16,7 @@ package net.mamoe.mirai.message.data
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.message.ContactMessage
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.message.MessageReceipt
|
||||
import net.mamoe.mirai.recallIn
|
||||
import net.mamoe.mirai.utils.LazyProperty
|
||||
@ -159,7 +159,7 @@ sealed class MessageSource : Message, MessageMetadata, ConstrainSingle<MessageSo
|
||||
* 此回执的 [消息源][MessageReceipt.source] 即为一个 [外向消息源][OnlineMessageSource.Outgoing], 代表着刚刚发出的那条消息的来源.
|
||||
*
|
||||
* #### 机器人接受消息
|
||||
* 当机器人接收一条消息 [ContactMessage], 这条消息包含一个 [内向消息源][OnlineMessageSource.Incoming], 代表着接收到的这条消息的来源.
|
||||
* 当机器人接收一条消息 [MessageEvent], 这条消息包含一个 [内向消息源][OnlineMessageSource.Incoming], 代表着接收到的这条消息的来源.
|
||||
*
|
||||
*
|
||||
* ### 实现
|
||||
@ -356,7 +356,7 @@ fun MessageSource.quote(): QuoteReply {
|
||||
}
|
||||
|
||||
/**
|
||||
* 引用这条消息. 仅从服务器接收的消息 (即来自 [ContactMessage]) 才可以通过这个方式被引用.
|
||||
* 引用这条消息. 仅从服务器接收的消息 (即来自 [MessageEvent]) 才可以通过这个方式被引用.
|
||||
* @see QuoteReply
|
||||
*/
|
||||
fun MessageChain.quote(): QuoteReply {
|
||||
|
@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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:JvmMultifileClass
|
||||
@file:JvmName("MessageEventKt")
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlinx.coroutines.TimeoutCancellationException
|
||||
import kotlinx.coroutines.async
|
||||
import net.mamoe.mirai.event.selectMessages
|
||||
import net.mamoe.mirai.event.syncFromEvent
|
||||
import net.mamoe.mirai.event.syncFromEventOrNull
|
||||
import net.mamoe.mirai.event.whileSelectMessages
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import net.mamoe.mirai.message.data.anyIsInstance
|
||||
import net.mamoe.mirai.message.data.firstIsInstance
|
||||
import net.mamoe.mirai.utils.PlannedRemoval
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.jvm.JvmMultifileClass
|
||||
import kotlin.jvm.JvmName
|
||||
import kotlin.jvm.JvmSynthetic
|
||||
|
||||
|
||||
/**
|
||||
* 判断两个 [MessageEvent] 的 [MessageEvent.sender] 和 [MessageEvent.subject] 是否相同
|
||||
*/
|
||||
fun MessageEvent.isContextIdenticalWith(another: MessageEvent): Boolean {
|
||||
return this.sender == another.sender && this.subject == another.subject
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessageEvent.sender] 和 [MessageEvent.subject] 与 [this] 相同且通过 [筛选][filter] 的 [MessageEvent]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @param filter 过滤器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
|
||||
*
|
||||
* @see syncFromEvent
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : MessageEvent> P.nextMessage(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): MessageChain {
|
||||
return syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessage) }?.takeIf { filter(it, it) }
|
||||
}.message
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessageEvent.sender] 和 [MessageEvent.subject] 与 [this] 相同且通过 [筛选][filter] 的 [MessageEvent]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @param filter 过滤器. 返回非 null 则代表得到了需要的值. [syncFromEvent] 会返回这个值
|
||||
* @return 消息链. 超时时返回 `null`
|
||||
*
|
||||
* @see syncFromEventOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : MessageEvent> P.nextMessageOrNull(
|
||||
timeoutMillis: Long = -1,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): MessageChain? {
|
||||
return syncFromEventOrNull<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageOrNull) }?.takeIf { filter(it, it) }
|
||||
}?.message
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessageEvent.sender] 和 [MessageEvent.subject] 与 [this] 相同的 [MessageEvent]
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
*
|
||||
* @throws TimeoutCancellationException
|
||||
*
|
||||
* @see syncFromEvent
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : MessageEvent> P.nextMessage(
|
||||
timeoutMillis: Long = -1
|
||||
): MessageChain {
|
||||
return syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessage) }
|
||||
}.message
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nextMessage
|
||||
* @throws TimeoutCancellationException
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : MessageEvent> P.nextMessageAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<MessageChain> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageAsync) }
|
||||
}.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nextMessage
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : MessageEvent> P.nextMessageAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
crossinline filter: suspend P.(P) -> Boolean
|
||||
): Deferred<MessageChain> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEvent<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageAsync) }
|
||||
.takeIf { filter(this, this) }
|
||||
}.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessageEvent.sender] 和 [MessageEvent.subject] 与 [this] 相同的 [MessageEvent]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @return 消息链. 超时时返回 `null`
|
||||
*
|
||||
* @see syncFromEventOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified P : MessageEvent> P.nextMessageOrNull(
|
||||
timeoutMillis: Long = -1
|
||||
): MessageChain? {
|
||||
return syncFromEventOrNull<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageOrNull) }
|
||||
}?.message
|
||||
}
|
||||
|
||||
/**
|
||||
* @see nextMessageOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
inline fun <reified P : MessageEvent> P.nextMessageOrNullAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<MessageChain?> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEventOrNull<P, P>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageOrNullAsync) }
|
||||
}?.message
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessageEvent.sender] 和 [MessageEvent.subject] 与 [this] 相同的 [MessageEvent]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
*
|
||||
* @see syncFromEvent
|
||||
* @see whileSelectMessages
|
||||
* @see selectMessages
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified M : Message> MessageEvent.nextMessageContaining(
|
||||
timeoutMillis: Long = -1
|
||||
): M {
|
||||
return syncFromEvent<MessageEvent, MessageEvent>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContaining) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}.message.firstIsInstance()
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
inline fun <reified M : Message> MessageEvent.nextMessageContainingAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<M> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
syncFromEvent<MessageEvent, MessageEvent>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingAsync) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}.message.firstIsInstance<M>()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 挂起当前协程, 等待下一条 [MessageEvent.sender] 和 [MessageEvent.subject] 与 [this] 相同并含有 [M] 类型的消息的 [MessageEvent]
|
||||
*
|
||||
* 若 [filter] 抛出了一个异常, 本函数会立即抛出这个异常.
|
||||
*
|
||||
* @param timeoutMillis 超时. 单位为毫秒. `-1` 为不限制
|
||||
* @return 指定类型的消息. 超时时返回 `null`
|
||||
*
|
||||
* @see syncFromEventOrNull
|
||||
*/
|
||||
@JvmSynthetic
|
||||
suspend inline fun <reified M : Message> MessageEvent.nextMessageContainingOrNull(
|
||||
timeoutMillis: Long = -1
|
||||
): M? {
|
||||
return syncFromEventOrNull<MessageEvent, MessageEvent>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingOrNull) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}?.message?.firstIsInstance()
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
inline fun <reified M : Message> MessageEvent.nextMessageContainingOrNullAsync(
|
||||
timeoutMillis: Long = -1,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||
): Deferred<M?> {
|
||||
return this.bot.async(coroutineContext) {
|
||||
syncFromEventOrNull<MessageEvent, MessageEvent>(timeoutMillis) {
|
||||
takeIf { this.isContextIdenticalWith(this@nextMessageContainingOrNullAsync) }
|
||||
.takeIf { this.message.anyIsInstance<M>() }
|
||||
}?.message?.firstIsInstance<M>()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@PlannedRemoval("1.2.0")
|
||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
||||
@Suppress("DEPRECATION_ERROR")
|
||||
@JvmSynthetic
|
||||
fun ContactMessage.isContextIdenticalWith(another: ContactMessage): Boolean {
|
||||
return this.sender == another.sender && this.subject == another.subject && this.bot == another.bot
|
||||
}
|
@ -7,50 +7,45 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("unused")
|
||||
@file:Suppress("unused", "DECLARATION_CANT_BE_INLINED")
|
||||
|
||||
package net.mamoe.mirai.message
|
||||
|
||||
import kotlinx.coroutines.io.ByteWriteChannel
|
||||
import kotlinx.io.core.Input
|
||||
import kotlinx.io.core.Output
|
||||
import kotlinx.io.core.use
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.Contact
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.User
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.utils.MiraiExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
import net.mamoe.mirai.utils.copyAndClose
|
||||
import net.mamoe.mirai.utils.copyTo
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import java.awt.image.BufferedImage
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
||||
import java.io.OutputStream
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* 一条从服务器接收到的消息事件.
|
||||
* JVM 平台相关扩展
|
||||
* 消息事件在 JVM 平台的扩展
|
||||
* @see MessageEventExtensions
|
||||
*/
|
||||
@Suppress("DEPRECATION")
|
||||
@Deprecated(
|
||||
message = "use ContactMessage",
|
||||
replaceWith = ReplaceWith("ContactMessage", "net.mamoe.mirai.message.ContactMessage")
|
||||
)
|
||||
@OptIn(MiraiInternalAPI::class, MiraiExperimentalAPI::class)
|
||||
actual abstract class MessagePacket<TSender : User, TSubject : Contact> actual constructor() :
|
||||
MessagePacketBase<TSender, TSubject>() {
|
||||
internal actual interface MessageEventPlatformExtensions<out TSender : User, out TSubject : Contact> {
|
||||
actual val subject: TSubject
|
||||
actual val sender: TSender
|
||||
actual val message: MessageChain
|
||||
actual val bot: Bot
|
||||
|
||||
// region 上传图片
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun uploadImage(image: BufferedImage): Image = subject.uploadImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun uploadImage(image: URL): Image = subject.uploadImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun uploadImage(image: Input): Image = subject.uploadImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun uploadImage(image: InputStream): Image = subject.uploadImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun uploadImage(image: File): Image = subject.uploadImage(image)
|
||||
// endregion
|
||||
@ -58,12 +53,16 @@ actual abstract class MessagePacket<TSender : User, TSubject : Contact> actual c
|
||||
// region 发送图片
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendImage(image: BufferedImage): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendImage(image: URL): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendImage(image: Input): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendImage(image: InputStream): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun sendImage(image: File): MessageReceipt<TSubject> = subject.sendImage(image)
|
||||
// endregion
|
||||
@ -71,12 +70,16 @@ actual abstract class MessagePacket<TSender : User, TSubject : Contact> actual c
|
||||
// region 上传图片 (扩展)
|
||||
@JvmSynthetic
|
||||
suspend inline fun BufferedImage.upload(): Image = upload(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun URL.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun Input.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun InputStream.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun File.uploadAsImage(): Image = uploadAsImage(subject)
|
||||
// endregion 上传图片 (扩展)
|
||||
@ -84,12 +87,16 @@ actual abstract class MessagePacket<TSender : User, TSubject : Contact> actual c
|
||||
// region 发送图片 (扩展)
|
||||
@JvmSynthetic
|
||||
suspend inline fun BufferedImage.send(): MessageReceipt<TSubject> = sendTo(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun URL.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun Input.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun InputStream.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
|
||||
@JvmSynthetic
|
||||
suspend inline fun File.sendAsImage(): MessageReceipt<TSubject> = sendAsImageTo(subject)
|
||||
// endregion 发送图片 (扩展)
|
Loading…
Reference in New Issue
Block a user