BotOnlineEvent, BotReloginEvent, BotOfflineEvent

This commit is contained in:
Him188 2021-04-21 12:57:58 +08:00
parent d70475b8ba
commit 84fa460b32
5 changed files with 68 additions and 10 deletions

View File

@ -10,10 +10,15 @@
package net.mamoe.mirai.internal
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import net.mamoe.mirai.Bot
import net.mamoe.mirai.Mirai
import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.event.events.BotOnlineEvent
import net.mamoe.mirai.event.events.BotReloginEvent
import net.mamoe.mirai.internal.contact.checkIsGroupImpl
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.component.ComponentStorage
@ -25,11 +30,9 @@ import net.mamoe.mirai.internal.network.handler.NetworkHandler
import net.mamoe.mirai.internal.network.handler.NetworkHandlerContextImpl
import net.mamoe.mirai.internal.network.handler.selector.FactoryKeepAliveNetworkHandlerSelector
import net.mamoe.mirai.internal.network.handler.selector.SelectorNetworkHandler
import net.mamoe.mirai.internal.network.handler.state.LoggingStateObserver
import net.mamoe.mirai.internal.network.handler.state.SafeStateObserver
import net.mamoe.mirai.internal.network.handler.state.StateObserver
import net.mamoe.mirai.internal.network.handler.state.safe
import net.mamoe.mirai.internal.network.handler.state.*
import net.mamoe.mirai.internal.network.impl.netty.NettyNetworkHandlerFactory
import net.mamoe.mirai.internal.network.impl.netty.asCoroutineExceptionHandler
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketWithRespType
import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
@ -78,6 +81,19 @@ internal class QQAndroidBot constructor(
val components = this
return StateObserver.chainOfNotNull(
components[BotInitProcessor].asObserver().safe(networkLogger),
StateChangedObserver(NetworkHandler.State.OK) { new ->
new.launch(logger.asCoroutineExceptionHandler()) {
BotOnlineEvent(bot).broadcast()
if (bot.firstLoginSucceed) { // TODO: 2021/4/21 actually no use
BotReloginEvent(bot, new.getCause()).broadcast()
}
}
},
StateChangedObserver(NetworkHandler.State.CLOSED) { new ->
new.launch(logger.asCoroutineExceptionHandler()) {
BotOfflineEvent.Dropped(bot, new.getCause()).broadcast()
}
},
debugConfiguration.stateObserver
)
}

View File

@ -142,6 +142,8 @@ internal abstract class NetworkHandlerSupport(
val correspondingState: NetworkHandler.State,
) : CoroutineScope by CoroutineScope(coroutineContext + Job(coroutineContext.job)) {
open fun getCause(): Throwable? = null
/**
* May throw any exception that caused the state to fail.
*/

View File

@ -12,6 +12,21 @@ package net.mamoe.mirai.internal.network.handler.state
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
import net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport
internal fun StateChangedObserver(
state: State,
action: (new: NetworkHandlerSupport.BaseStateImpl) -> Unit
): StateChangedObserver {
return object : StateChangedObserver(state) {
override fun stateChanged0(
networkHandler: NetworkHandlerSupport,
previous: NetworkHandlerSupport.BaseStateImpl,
new: NetworkHandlerSupport.BaseStateImpl
) {
action(new)
}
}
}
internal abstract class StateChangedObserver(
val state: State,
) : StateObserver {

View File

@ -205,16 +205,20 @@ internal class NettyNetworkHandler(
context[SsoProcessor].login(this@NettyNetworkHandler)
}.apply {
invokeOnCompletion { error ->
if (error != null) setState {
StateConnecting(
collectiveExceptions.apply { collect(error) },
wait = true
)
} // logon failure closes the network handler.
if (error != null) {
setState {
StateConnecting(
collectiveExceptions.apply { collect(error) },
wait = true
)
} // logon failure closes the network handler.
}
// and this error will also be thrown by `StateConnecting.resumeConnection`
}
}
override fun getCause(): Throwable? = collectiveExceptions.getLast()
override suspend fun sendPacketImpl(packet: OutgoingPacket) {
connection.await() // split line number
.writeAndFlush(packet)
@ -316,6 +320,8 @@ internal class NettyNetworkHandler(
private inner class StateConnectionLost(
private val cause: Throwable?
) : NettyState(State.CONNECTION_LOST) {
override fun getCause(): Throwable? = cause
override suspend fun sendPacketImpl(packet: OutgoingPacket) {
throw IllegalStateException(
"Internal error: connection is lost so cannot send packet. Call resumeConnection first.",
@ -336,6 +342,7 @@ internal class NettyNetworkHandler(
closeSuper(exception)
}
override fun getCause(): Throwable? = exception
override suspend fun sendPacketImpl(packet: OutgoingPacket) = error("NetworkHandler is already closed.")
override suspend fun resumeConnection0() {
exception?.let { throw it }

View File

@ -12,7 +12,12 @@ package net.mamoe.mirai.internal.network.impl.netty
import io.netty.buffer.ByteBuf
import io.netty.buffer.ByteBufInputStream
import io.netty.channel.ChannelFuture
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineName
import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.SimpleLogger
import net.mamoe.mirai.utils.SimpleLogger.LogPriority.ERROR
internal suspend fun ChannelFuture.awaitKt(): ChannelFuture {
@ -37,3 +42,16 @@ internal fun ByteBuf.toReadPacket(): ByteReadPacket {
ByteBufInputStream(buf).withUse { copyTo(outputStream()) }
}
}
internal fun MiraiLogger.asCoroutineExceptionHandler(
priority: SimpleLogger.LogPriority = ERROR
): CoroutineExceptionHandler {
return CoroutineExceptionHandler { context, e ->
call(
priority,
context[CoroutineName]?.let { "Exception in coroutine '${it.name}'." } ?: "Exception in unnamed coroutine.",
e
)
}
}