Commit e3c3c712 authored by Him188's avatar Him188

Fix events

parent 8178a8c8
...@@ -2,10 +2,7 @@ ...@@ -2,10 +2,7 @@
package net.mamoe.mirai.event package net.mamoe.mirai.event
import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.newCoroutineContext
import kotlinx.coroutines.withContext
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.event.internal.broadcastInternal import net.mamoe.mirai.event.internal.broadcastInternal
import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.BotNetworkHandler
...@@ -66,8 +63,9 @@ interface Cancellable { ...@@ -66,8 +63,9 @@ interface Cancellable {
/** /**
* 广播一个事件的唯一途径. * 广播一个事件的唯一途径.
* 若 [context] 不包含 [CoroutineExceptionHandler], 将会使用默认的异常捕获, 即 [error] * 这个方法将会把处理挂起在 [context] 下运行. 默认为使用 [EventDispatcher] 调度事件协程.
* 也就是说, 这个方法不会抛出异常, 只会把异常交由 [context] 捕获 *
* @param context 事件处理协程运行的 [CoroutineContext].
*/ */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
@JvmOverloads @JvmOverloads
...@@ -84,13 +82,23 @@ suspend fun <E : Event> E.broadcast(context: CoroutineContext = EmptyCoroutineCo ...@@ -84,13 +82,23 @@ suspend fun <E : Event> E.broadcast(context: CoroutineContext = EmptyCoroutineCo
} }
} }
/**
* 事件协程调度器.
*
* JVM: 共享 [Dispatchers.Default]
*/
internal expect val EventDispatcher: CoroutineDispatcher
/** /**
* 事件协程作用域. * 事件协程作用域.
* 所有的事件 [broadcast] 过程均在此作用域下运行. * 所有的事件 [broadcast] 过程均在此作用域下运行.
* *
* 然而, 若在事件处理过程中使用到 [Contact.sendMessage] 等会 [发送数据包][BotNetworkHandler.sendPacket] 的方法, * 然而, 若在事件处理过程中使用到 [Contact.sendMessage] 等会 [发送数据包][BotNetworkHandler.sendPacket] 的方法,
* 发送过程将会通过 [withContext] 将协程切换到 [BotNetworkHandler.NetworkScope] * 发送过程将会通过 [withContext] 将协程切换到 [BotNetworkHandler] 作用域下执行.
*/ */
object EventScope : CoroutineScope { object EventScope : CoroutineScope {
override val coroutineContext: CoroutineContext = EmptyCoroutineContext override val coroutineContext: CoroutineContext =
EventDispatcher + CoroutineExceptionHandler { _, e ->
MiraiLogger.error("An exception is thrown in EventScope", e)
}
} }
\ No newline at end of file
...@@ -173,7 +173,12 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>( ...@@ -173,7 +173,12 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>(
* @param trim `true` 则删除首尾空格后比较 * @param trim `true` 则删除首尾空格后比较
* @param ignoreCase `true` 则不区分大小写 * @param ignoreCase `true` 则不区分大小写
*/ */
suspend fun case(equals: String, trim: Boolean = true, ignoreCase: Boolean = false, onEvent: @MessageDsl suspend T.(String) -> Unit) = suspend fun case(
equals: String,
trim: Boolean = true,
ignoreCase: Boolean = false,
onEvent: @MessageDsl suspend T.(String) -> Unit
) =
content({ equals.equals(if (trim) it.trim() else it, ignoreCase = ignoreCase) }, onEvent) content({ equals.equals(if (trim) it.trim() else it, ignoreCase = ignoreCase) }, onEvent)
/** /**
...@@ -184,7 +189,11 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>( ...@@ -184,7 +189,11 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>(
/** /**
* 如果消息的前缀是 [prefix], 就执行 [onEvent] * 如果消息的前缀是 [prefix], 就执行 [onEvent]
*/ */
suspend fun startsWith(prefix: String, removePrefix: Boolean = false, onEvent: @MessageDsl suspend T.(String) -> Unit) = suspend fun startsWith(
prefix: String,
removePrefix: Boolean = false,
onEvent: @MessageDsl suspend T.(String) -> Unit
) =
content({ it.startsWith(prefix) }) { content({ it.startsWith(prefix) }) {
if (removePrefix) this.onEvent(this.message.stringValue.substringAfter(prefix)) if (removePrefix) this.onEvent(this.message.stringValue.substringAfter(prefix))
else onEvent(this) else onEvent(this)
...@@ -199,7 +208,8 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>( ...@@ -199,7 +208,8 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>(
/** /**
* 如果是这个人发的消息, 就执行 [onEvent]. 消息可以是好友消息也可以是群消息 * 如果是这个人发的消息, 就执行 [onEvent]. 消息可以是好友消息也可以是群消息
*/ */
suspend fun sentBy(qqId: UInt, onEvent: @MessageDsl suspend T.(String) -> Unit) = content({ sender.id == qqId }, onEvent) suspend fun sentBy(qqId: UInt, onEvent: @MessageDsl suspend T.(String) -> Unit) =
content({ sender.id == qqId }, onEvent)
/** /**
* 如果是这个人发的消息, 就执行 [onEvent]. 消息可以是好友消息也可以是群消息 * 如果是这个人发的消息, 就执行 [onEvent]. 消息可以是好友消息也可以是群消息
...@@ -231,15 +241,22 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>( ...@@ -231,15 +241,22 @@ class MessageSubscribersBuilder<T : SenderAndMessage<*>>(
suspend infix fun String.caseReply(replier: String) = case(this, true) { this@case.reply(replier) } suspend infix fun String.caseReply(replier: String) = case(this, true) { this@case.reply(replier) }
suspend infix fun String.caseReply(replier: StringReplier<T>) = case(this, true) { this@case.reply(replier(this)) } suspend infix fun String.caseReply(replier: StringReplier<T>) = case(this, true) { this@case.reply(replier(this)) }
suspend infix fun String.containsReply(replier: String) = content({ this@containsReply in it }) { this@content.reply(replier) } suspend infix fun String.containsReply(replier: String) =
content({ this@containsReply in it }) { this@content.reply(replier) }
suspend infix fun String.containsReply(replier: StringReplier<T>) = content({ this@containsReply in it }) { replier(this) } suspend infix fun String.containsReply(replier: StringReplier<T>) =
content({ this@containsReply in it }) { replier(this) }
suspend infix fun String.startsWithReply(replier: StringReplier<T>) = content({ it.startsWith(this@startsWithReply) }) { replier(this) } suspend infix fun String.startsWithReply(replier: StringReplier<T>) =
content({ it.startsWith(this@startsWithReply) }) { replier(this) }
suspend infix fun String.endswithReply(replier: StringReplier<T>) = content({ it.endsWith(this@endswithReply) }) { replier(this) } suspend infix fun String.endswithReply(replier: StringReplier<T>) =
content({ it.endsWith(this@endswithReply) }) { replier(this) }
suspend infix fun String.reply(reply: String) = case(this) {
this@case.reply(reply)
}
suspend infix fun String.reply(reply: String) = case(this) { this@case.reply(reply) }
suspend infix fun String.reply(reply: StringReplier<T>) = case(this) { this@case.reply(reply(this)) } suspend infix fun String.reply(reply: StringReplier<T>) = case(this) { this@case.reply(reply(this)) }
......
...@@ -22,6 +22,10 @@ enum class ListeningStatus { ...@@ -22,6 +22,10 @@ enum class ListeningStatus {
// region 顶层方法 // region 顶层方法
/**
* 订阅所有 [E] 及其子类事件.
* 在
*/
suspend inline fun <reified E : Event> subscribe(noinline handler: suspend (E) -> ListeningStatus) = E::class.subscribe(handler) suspend inline fun <reified E : Event> subscribe(noinline handler: suspend (E) -> ListeningStatus) = E::class.subscribe(handler)
suspend inline fun <reified E : Event> subscribeAlways(noinline listener: suspend (E) -> Unit) = E::class.subscribeAlways(listener) suspend inline fun <reified E : Event> subscribeAlways(noinline listener: suspend (E) -> Unit) = E::class.subscribeAlways(listener)
......
...@@ -6,12 +6,14 @@ import kotlinx.coroutines.sync.Mutex ...@@ -6,12 +6,14 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.EventLogger
import net.mamoe.mirai.event.EventScope import net.mamoe.mirai.event.EventScope
import net.mamoe.mirai.event.ListeningStatus import net.mamoe.mirai.event.ListeningStatus
import net.mamoe.mirai.event.events.BotEvent import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.utils.internal.inlinedRemoveIf import net.mamoe.mirai.utils.internal.inlinedRemoveIf
import kotlin.jvm.JvmField import kotlin.jvm.JvmField
import kotlin.reflect.KClass import kotlin.reflect.KClass
import kotlin.reflect.KFunction
/** /**
* 监听和广播实现. * 监听和广播实现.
...@@ -25,6 +27,7 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener< ...@@ -25,6 +27,7 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<
if (mainMutex.tryLock(listener)) {//能锁则代表这个事件目前没有正在广播. if (mainMutex.tryLock(listener)) {//能锁则代表这个事件目前没有正在广播.
try { try {
add(listener)//直接修改主监听者列表 add(listener)//直接修改主监听者列表
EventLogger.debug("Added a listener to ${this@subscribeInternal.simpleName}")
} finally { } finally {
mainMutex.unlock(listener) mainMutex.unlock(listener)
} }
...@@ -34,6 +37,7 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener< ...@@ -34,6 +37,7 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<
//不能锁住, 则这个事件正在广播, 那么要将新的监听者放入缓存 //不能锁住, 则这个事件正在广播, 那么要将新的监听者放入缓存
cacheMutex.withLock { cacheMutex.withLock {
cache.add(listener) cache.add(listener)
EventLogger.debug("Added a listener to cache of ${this@subscribeInternal.simpleName}")
} }
EventScope.launch { EventScope.launch {
...@@ -44,6 +48,7 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener< ...@@ -44,6 +48,7 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<
if (cache.size != 0) { if (cache.size != 0) {
addAll(cache) addAll(cache)
cache.clear() cache.clear()
EventLogger.debug("Cache of ${this@subscribeInternal.simpleName} is now transferred to main")
} }
} }
} }
...@@ -61,7 +66,7 @@ sealed class Listener<in E : Event> { ...@@ -61,7 +66,7 @@ sealed class Listener<in E : Event> {
} }
@PublishedApi @PublishedApi
internal class Handler<E : Event>(@JvmField val handler: suspend (E) -> ListeningStatus) : Listener<E>() { internal class Handler<in E : Event>(@JvmField val handler: suspend (E) -> ListeningStatus) : Listener<E>() {
override suspend fun onEvent(event: E): ListeningStatus = handler.invoke(event) override suspend fun onEvent(event: E): ListeningStatus = handler.invoke(event)
} }
...@@ -89,7 +94,7 @@ internal class HandlerWithBot<E : Event>(val bot: Bot, @JvmField val handler: su ...@@ -89,7 +94,7 @@ internal class HandlerWithBot<E : Event>(val bot: Bot, @JvmField val handler: su
/** /**
* 这个事件类的监听器 list * 这个事件类的监听器 list
*/ */
internal suspend fun <E : Event> KClass<E>.listeners(): EventListeners<E> = EventListenerManger.get(this) internal suspend fun <E : Event> KClass<out E>.listeners(): EventListeners<E> = EventListenerManger.get(this)
internal class EventListeners<E : Event> : MutableList<Listener<E>> by mutableListOf() { internal class EventListeners<E : Event> : MutableList<Listener<E>> by mutableListOf() {
/** /**
...@@ -105,6 +110,14 @@ internal class EventListeners<E : Event> : MutableList<Listener<E>> by mutableLi ...@@ -105,6 +110,14 @@ internal class EventListeners<E : Event> : MutableList<Listener<E>> by mutableLi
* 等待加入到主 list 的监听者. 务必使用 [cacheMutex] * 等待加入到主 list 的监听者. 务必使用 [cacheMutex]
*/ */
val cache: MutableList<Listener<E>> = mutableListOf() val cache: MutableList<Listener<E>> = mutableListOf()
init {
this::class.members.filterIsInstance<KFunction<*>>().forEach {
if (it.name == "add") {
it.isExternal
}
}
}
} }
/** /**
...@@ -112,11 +125,11 @@ internal class EventListeners<E : Event> : MutableList<Listener<E>> by mutableLi ...@@ -112,11 +125,11 @@ internal class EventListeners<E : Event> : MutableList<Listener<E>> by mutableLi
* [EventListeners] 是 lazy 的: 它们只会在被需要的时候才创建和存储. * [EventListeners] 是 lazy 的: 它们只会在被需要的时候才创建和存储.
*/ */
internal object EventListenerManger { internal object EventListenerManger {
private val registries: MutableMap<KClass<out Event>, EventListeners<out Event>> = mutableMapOf() private val registries: MutableMap<KClass<out Event>, EventListeners<*>> = mutableMapOf()
private val registriesMutex = Mutex() private val registriesMutex = Mutex()
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
internal suspend fun <E : Event> get(clazz: KClass<E>): EventListeners<E> = registriesMutex.withLock { internal suspend fun <E : Event> get(clazz: KClass<out E>): EventListeners<E> = registriesMutex.withLock {
if (registries.containsKey(clazz)) { if (registries.containsKey(clazz)) {
return registries[clazz] as EventListeners<E> return registries[clazz] as EventListeners<E>
} else { } else {
...@@ -128,11 +141,9 @@ internal object EventListenerManger { ...@@ -128,11 +141,9 @@ internal object EventListenerManger {
} }
} }
@Suppress("UNCHECKED_CAST")
internal suspend fun <E : Event> E.broadcastInternal(): E { internal suspend fun <E : Event> E.broadcastInternal(): E {
suspend fun callListeners(listeners: EventListeners<in E>) { suspend fun callListeners(listeners: EventListeners<in E>) {
suspend fun callAndRemoveIfRequired() { suspend fun callAndRemoveIfRequired() = listeners.inlinedRemoveIf {
listeners.inlinedRemoveIf {
if (it.lock.tryLock()) { if (it.lock.tryLock()) {
try { try {
it.onEvent(this) == ListeningStatus.STOPPED it.onEvent(this) == ListeningStatus.STOPPED
...@@ -141,33 +152,38 @@ internal suspend fun <E : Event> E.broadcastInternal(): E { ...@@ -141,33 +152,38 @@ internal suspend fun <E : Event> E.broadcastInternal(): E {
} }
} else false } else false
} }
}
//自己持有, 则是在一个事件中 //自己持有, 则是在一个事件中
if (listeners.mainMutex.holdsLock(listeners)) { if (listeners.mainMutex.holdsLock(listeners)) {
callAndRemoveIfRequired() callAndRemoveIfRequired()
} else { } else {
while (!listeners.mainMutex.tryLock(this)) { while (!listeners.mainMutex.tryLock(listeners)) {
delay(10) delay(10)
} }
try { try {
callAndRemoveIfRequired() callAndRemoveIfRequired()
} finally { } finally {
listeners.mainMutex.unlock(this) listeners.mainMutex.unlock(listeners)
} }
} }
} }
callListeners(this::class.listeners() as EventListeners<in E>) callListeners(this::class.listeners())
applyAllListeners(this::class) { callListeners(it as EventListeners<in E>) } applySuperListeners(this::class) { callListeners(it) }
return this return this
} }
private suspend inline fun <E : Event> applyAllListeners( /**
clazz: KClass<E>, * apply [block] to all the [EventListeners] in [clazz]'s superclasses
block: (EventListeners<in E>) -> Unit */
) = clazz.supertypes.map { it.classifier }.filterIsInstance<KClass<out Event>>().forEach { private tailrec suspend fun <E : Event> applySuperListeners(
clazz: KClass<out E>,
block: suspend (EventListeners<in E>) -> Unit
) {
val superEventClass =
clazz.supertypes.map { it.classifier }.filterIsInstance<KClass<out Event>>().firstOrNull() ?: return
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
block(it.listeners() as EventListeners<in E>) block(superEventClass.listeners() as EventListeners<in E>)
applySuperListeners(superEventClass, block)
} }
\ No newline at end of file
...@@ -29,6 +29,13 @@ import net.mamoe.mirai.utils.io.* ...@@ -29,6 +29,13 @@ import net.mamoe.mirai.utils.io.*
import net.mamoe.mirai.utils.solveCaptcha import net.mamoe.mirai.utils.solveCaptcha
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
/**
* 包处理协程调度器.
*
* JVM: 独立的 4 thread 调度器
*/
expect val NetworkDispatcher: CoroutineDispatcher
/** /**
* [BotNetworkHandler] 的 TIM PC 协议实现 * [BotNetworkHandler] 的 TIM PC 协议实现
* *
...@@ -38,7 +45,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) : ...@@ -38,7 +45,7 @@ internal class TIMBotNetworkHandler internal constructor(private val bot: Bot) :
BotNetworkHandler<TIMBotNetworkHandler.BotSocketAdapter>, PacketHandlerList() { BotNetworkHandler<TIMBotNetworkHandler.BotSocketAdapter>, PacketHandlerList() {
override val coroutineContext: CoroutineContext = override val coroutineContext: CoroutineContext =
Dispatchers.Default + CoroutineExceptionHandler { _, e -> NetworkDispatcher + CoroutineExceptionHandler { _, e ->
bot.logger.error("An exception was thrown in a coroutine under TIMBotNetworkHandler", e) bot.logger.error("An exception was thrown in a coroutine under TIMBotNetworkHandler", e)
} + SupervisorJob() } + SupervisorJob()
......
...@@ -19,6 +19,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.event.IgnoredServerEventPacke ...@@ -19,6 +19,7 @@ import net.mamoe.mirai.network.protocol.tim.packet.event.IgnoredServerEventPacke
import net.mamoe.mirai.network.protocol.tim.packet.event.ServerFriendMessageEventPacket import net.mamoe.mirai.network.protocol.tim.packet.event.ServerFriendMessageEventPacket
import net.mamoe.mirai.network.protocol.tim.packet.event.ServerGroupMessageEventPacket import net.mamoe.mirai.network.protocol.tim.packet.event.ServerGroupMessageEventPacket
import net.mamoe.mirai.network.protocol.tim.packet.event.ServerGroupUploadFileEventPacket import net.mamoe.mirai.network.protocol.tim.packet.event.ServerGroupUploadFileEventPacket
import net.mamoe.mirai.network.qqAccount
/** /**
* 处理消息事件, 承担消息发送任务. * 处理消息事件, 承担消息发送任务.
...@@ -69,10 +70,17 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) { ...@@ -69,10 +70,17 @@ class EventPacketHandler(session: BotSession) : PacketHandler(session) {
} }
suspend fun sendFriendMessage(qq: QQ, message: MessageChain) { suspend fun sendFriendMessage(qq: QQ, message: MessageChain) {
session.socket.sendPacket(SendFriendMessagePacket(session.bot.account.id, qq.id, session.sessionKey, message)) session.socket.sendPacket(SendFriendMessagePacket(session.qqAccount, qq.id, session.sessionKey, message))
} }
suspend fun sendGroupMessage(group: Group, message: MessageChain) { suspend fun sendGroupMessage(group: Group, message: MessageChain) {
session.socket.sendPacket(SendGroupMessagePacket(session.bot.account.id, group.internalId, session.sessionKey, message)) session.socket.sendPacket(
SendGroupMessagePacket(
session.qqAccount,
group.internalId,
session.sessionKey,
message
)
)
} }
} }
\ No newline at end of file
...@@ -18,7 +18,7 @@ class OutgoingPacket( ...@@ -18,7 +18,7 @@ class OutgoingPacket(
name: String?, name: String?,
override val packetId: PacketId, override val packetId: PacketId,
override val sequenceId: UShort, override val sequenceId: UShort,
val delegate: ByteReadPacket internal val delegate: ByteReadPacket
) : Packet { ) : Packet {
private val name: String by lazy { private val name: String by lazy {
name ?: packetId.toString() name ?: packetId.toString()
...@@ -49,7 +49,7 @@ interface OutgoingPacketBuilder { ...@@ -49,7 +49,7 @@ interface OutgoingPacketBuilder {
private val sequenceIdInternal = atomic(1) private val sequenceIdInternal = atomic(1)
@PublishedApi @PublishedApi
internal fun atomicNextSequenceId() = sequenceIdInternal.getAndIncrement().toUShort() internal fun atomicNextSequenceId(): UShort = sequenceIdInternal.getAndIncrement().toUShort()
} }
} }
......
...@@ -160,7 +160,7 @@ internal fun Packet.packetToString(name: String = this::class.simpleName.toStrin ...@@ -160,7 +160,7 @@ internal fun Packet.packetToString(name: String = this::class.simpleName.toStrin
PacketNameFormatter.adjustName(name + "(${this.idHexString})") + PacketNameFormatter.adjustName(name + "(${this.idHexString})") +
this::class.members this::class.members
.filterIsInstance<KProperty<*>>() .filterIsInstance<KProperty<*>>()
.filterNot { it.isConst || it.isSuspend || it.visibility == KVisibility.PRIVATE } .filterNot { it.isConst || it.isSuspend || it.visibility != KVisibility.PUBLIC }
.filterNot { prop -> prop.name in IgnoreIdListEquals || IgnoreIdListInclude.any { it in prop.name } } .filterNot { prop -> prop.name in IgnoreIdListEquals || IgnoreIdListInclude.any { it in prop.name } }
.joinToString(", ", "{", "}") { it.briefDescription(this@packetToString) } .joinToString(", ", "{", "}") { it.briefDescription(this@packetToString) }
......
package net.mamoe.mirai.event
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
internal actual val EventDispatcher: CoroutineDispatcher get() = Dispatchers.Default
\ No newline at end of file
package net.mamoe.mirai.network.protocol.tim
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.Executors
/**
* 独立的 4 thread 调度器
*/
actual val NetworkDispatcher: CoroutineDispatcher
get() = Executors.newFixedThreadPool(4).asCoroutineDispatcher()
\ No newline at end of file
...@@ -7,6 +7,8 @@ import kotlinx.coroutines.launch ...@@ -7,6 +7,8 @@ import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.BotAccount import net.mamoe.mirai.BotAccount
import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.event.subscribeMessages import net.mamoe.mirai.event.subscribeMessages
import net.mamoe.mirai.login import net.mamoe.mirai.login
import net.mamoe.mirai.network.protocol.tim.packet.login.requireSuccess import net.mamoe.mirai.network.protocol.tim.packet.login.requireSuccess
...@@ -35,6 +37,13 @@ suspend fun main() { ...@@ -35,6 +37,13 @@ suspend fun main() {
) )
).apply { login().requireSuccess() } ).apply { login().requireSuccess() }
/**
* 监听所有事件
*/
subscribeAlways<Event> {
//bot.logger.verbose("收到了一个事件: ${it::class.simpleName}")
}
bot.subscribeMessages { bot.subscribeMessages {
"你好" reply "你好!" "你好" reply "你好!"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment