Fix sso and event logging

This commit is contained in:
Him188 2021-04-25 17:22:46 +08:00
parent 971685a2b0
commit 5fa54114c1
18 changed files with 114 additions and 69 deletions

View File

@ -14,9 +14,13 @@ package net.mamoe.mirai.event
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.internal.event.broadcastInternal import net.mamoe.mirai.internal.event.broadcastInternal
import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.JavaFriendlyAPI import net.mamoe.mirai.utils.JavaFriendlyAPI
import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.MiraiExperimentalApi
import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.verbose
/** /**
* 可被监听的类, 可以是任何 class object. * 可被监听的类, 可以是任何 class object.
@ -149,6 +153,14 @@ public suspend fun <E : Event> E.broadcast(): E = apply {
} }
this.broadCastLock.withLock { this.broadCastLock.withLock {
this._intercepted = false this._intercepted = false
if (EventDisabled) return@withLock
if (this is Packet.NoEventLog) return@withLock
if (this is Packet) return@withLock // all [Packet]s are logged in [LoggingPacketHandler]
if (this is BotEvent) {
this.bot.logger.verbose { "Event: $this" }
} else {
MiraiLogger.TopLevel.verbose { "Event: $this" }
}
this.broadcastInternal() // inline, no extra cost this.broadcastInternal() // inline, no extra cost
} }
} }

View File

@ -100,7 +100,6 @@ internal object GlobalEventListeners {
// inline: NO extra Continuation // inline: NO extra Continuation
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
internal suspend inline fun AbstractEvent.broadcastInternal() { internal suspend inline fun AbstractEvent.broadcastInternal() {
if (EventDisabled) return
callAndRemoveIfRequired(this@broadcastInternal) callAndRemoveIfRequired(this@broadcastInternal)
} }

View File

@ -21,6 +21,7 @@ import kotlinx.serialization.json.*
import net.mamoe.mirai.* import net.mamoe.mirai.*
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.* import net.mamoe.mirai.data.*
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent import net.mamoe.mirai.event.events.BotInvitedJoinGroupRequestEvent
import net.mamoe.mirai.event.events.FriendAddEvent import net.mamoe.mirai.event.events.FriendAddEvent
import net.mamoe.mirai.event.events.MemberJoinRequestEvent import net.mamoe.mirai.event.events.MemberJoinRequestEvent
@ -43,7 +44,6 @@ import net.mamoe.mirai.internal.network.protocol.packet.login.StatSvc
import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect import net.mamoe.mirai.internal.network.protocol.packet.sendAndExpect
import net.mamoe.mirai.internal.network.protocol.packet.summarycard.SummaryCard import net.mamoe.mirai.internal.network.protocol.packet.summarycard.SummaryCard
import net.mamoe.mirai.internal.utils.MiraiProtocolInternal import net.mamoe.mirai.internal.utils.MiraiProtocolInternal
import net.mamoe.mirai.internal.utils.broadcastWithBot
import net.mamoe.mirai.internal.utils.crypto.TEA import net.mamoe.mirai.internal.utils.crypto.TEA
import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
@ -156,7 +156,7 @@ internal open class MiraiImpl : IMirai, LowLevelApiAccessor {
) )
event.bot.getFriend(event.fromId)?.let { friend -> event.bot.getFriend(event.fromId)?.let { friend ->
FriendAddEvent(friend).broadcastWithBot(event.bot) FriendAddEvent(friend).broadcast()
} }
} }

View File

@ -10,6 +10,7 @@
package net.mamoe.mirai.internal package net.mamoe.mirai.internal
import kotlinx.atomicfu.atomic
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
@ -30,6 +31,8 @@ import net.mamoe.mirai.internal.network.context.SsoProcessorContextImpl
import net.mamoe.mirai.internal.network.handler.NetworkHandler import net.mamoe.mirai.internal.network.handler.NetworkHandler
import net.mamoe.mirai.internal.network.handler.NetworkHandler.State import net.mamoe.mirai.internal.network.handler.NetworkHandler.State
import net.mamoe.mirai.internal.network.handler.NetworkHandlerContextImpl import net.mamoe.mirai.internal.network.handler.NetworkHandlerContextImpl
import net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport
import net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport.BaseStateImpl
import net.mamoe.mirai.internal.network.handler.selector.FactoryKeepAliveNetworkHandlerSelector 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.selector.SelectorNetworkHandler
import net.mamoe.mirai.internal.network.handler.state.* import net.mamoe.mirai.internal.network.handler.state.*
@ -103,11 +106,18 @@ internal open class QQAndroidBot constructor(
val components = this val components = this
return StateObserver.chainOfNotNull( return StateObserver.chainOfNotNull(
components[BotInitProcessor].asObserver(), components[BotInitProcessor].asObserver(),
StateChangedObserver(to = State.OK) { new -> object : StateChangedObserver(State.OK) {
bot.launch(logger.asCoroutineExceptionHandler()) { private val shouldBroadcastRelogin = atomic(false)
BotOnlineEvent(bot).broadcast() override fun stateChanged0(
if (bot.components[SsoProcessor].firstLoginSucceed) { // TODO: 2021/4/21 actually no use networkHandler: NetworkHandlerSupport,
BotReloginEvent(bot, new.getCause()).broadcast() previous: BaseStateImpl,
new: BaseStateImpl
) {
bot.launch(logger.asCoroutineExceptionHandler()) {
BotOnlineEvent(bot).broadcast()
if (shouldBroadcastRelogin.compareAndSet(false, true)) {
BotReloginEvent(bot, new.getCause()).broadcast()
}
} }
} }
}, },
@ -155,8 +165,9 @@ internal open class QQAndroidBot constructor(
set(ServerList, ServerListImpl()) set(ServerList, ServerListImpl())
set( set(
PacketHandler, PacketHandlerChain( PacketHandler, PacketHandlerChain(
LoggingPacketHandler(bot, components, networkLogger), LoggingPacketHandler(bot, networkLogger),
EventBroadcasterPacketHandler(bot, components, logger) EventBroadcasterPacketHandler(networkLogger),
CallPacketFactoryPacketHandler(bot)
) )
) )
set(PacketCodec, PacketCodecImpl()) set(PacketCodec, PacketCodecImpl())

View File

@ -38,7 +38,6 @@ import net.mamoe.mirai.internal.network.protocol.packet.chat.voice.voiceCodec
import net.mamoe.mirai.internal.network.protocol.packet.list.ProfileService import net.mamoe.mirai.internal.network.protocol.packet.list.ProfileService
import net.mamoe.mirai.internal.utils.GroupPkgMsgParsingCache import net.mamoe.mirai.internal.utils.GroupPkgMsgParsingCache
import net.mamoe.mirai.internal.utils.RemoteFileImpl import net.mamoe.mirai.internal.utils.RemoteFileImpl
import net.mamoe.mirai.internal.utils.broadcastWithBot
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
@ -111,7 +110,7 @@ internal class GroupImpl(
} }
} }
} }
BotLeaveEvent.Active(this).broadcastWithBot(bot) BotLeaveEvent.Active(this).broadcast()
return true return true
} }

View File

@ -13,16 +13,18 @@ package net.mamoe.mirai.internal.contact
import kotlinx.atomicfu.AtomicInt import kotlinx.atomicfu.AtomicInt
import kotlinx.atomicfu.atomic import kotlinx.atomicfu.atomic
import kotlinx.coroutines.* import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.cancel
import kotlinx.coroutines.launch
import net.mamoe.mirai.LowLevelApi import net.mamoe.mirai.LowLevelApi
import net.mamoe.mirai.contact.* import net.mamoe.mirai.contact.*
import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.internal.message.OnlineMessageSourceToTempImpl import net.mamoe.mirai.internal.message.OnlineMessageSourceToTempImpl
import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopManagement import net.mamoe.mirai.internal.network.protocol.packet.chat.TroopManagement
import net.mamoe.mirai.internal.utils.broadcastWithBot
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.Message
import net.mamoe.mirai.utils.cast import net.mamoe.mirai.utils.cast
import net.mamoe.mirai.utils.currentTimeSeconds import net.mamoe.mirai.utils.currentTimeSeconds
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
@ -99,7 +101,7 @@ internal class NormalMemberImpl constructor(
newValue newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
MemberCardChangeEvent(oldValue, newValue, this@NormalMemberImpl).broadcastWithBot(bot) MemberCardChangeEvent(oldValue, newValue, this@NormalMemberImpl).broadcast()
} }
} }
} }
@ -119,7 +121,7 @@ internal class NormalMemberImpl constructor(
newValue newValue
).sendWithoutExpect() ).sendWithoutExpect()
} }
MemberSpecialTitleChangeEvent(oldValue, newValue, this@NormalMemberImpl, null).broadcastWithBot(bot) MemberSpecialTitleChangeEvent(oldValue, newValue, this@NormalMemberImpl, null).broadcast()
} }
} }
} }
@ -142,7 +144,7 @@ internal class NormalMemberImpl constructor(
} }
@Suppress("RemoveRedundantQualifierName") // or unresolved reference @Suppress("RemoveRedundantQualifierName") // or unresolved reference
net.mamoe.mirai.event.events.MemberMuteEvent(this@NormalMemberImpl, durationSeconds, null).broadcastWithBot(bot) (net.mamoe.mirai.event.events.MemberMuteEvent(this@NormalMemberImpl, durationSeconds, null).broadcast())
this._muteTimestamp = currentTimeSeconds().toInt() + durationSeconds this._muteTimestamp = currentTimeSeconds().toInt() + durationSeconds
} }
@ -158,7 +160,7 @@ internal class NormalMemberImpl constructor(
} }
@Suppress("RemoveRedundantQualifierName") // or unresolved reference @Suppress("RemoveRedundantQualifierName") // or unresolved reference
net.mamoe.mirai.event.events.MemberUnmuteEvent(this@NormalMemberImpl, null).broadcastWithBot(bot) (net.mamoe.mirai.event.events.MemberUnmuteEvent(this@NormalMemberImpl, null).broadcast())
this._muteTimestamp = 0 this._muteTimestamp = 0
} }
@ -179,7 +181,7 @@ internal class NormalMemberImpl constructor(
@Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") @Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE")
group.members.delegate.removeIf { it.id == this@NormalMemberImpl.id } group.members.delegate.removeIf { it.id == this@NormalMemberImpl.id }
this@NormalMemberImpl.cancel(CancellationException("Kicked by bot")) this@NormalMemberImpl.cancel(CancellationException("Kicked by bot"))
MemberLeaveEvent.Kick(this@NormalMemberImpl, null).broadcastWithBot(bot) MemberLeaveEvent.Kick(this@NormalMemberImpl, null).broadcast()
} }
} }
@ -208,7 +210,7 @@ internal class NormalMemberImpl constructor(
this@NormalMemberImpl.permission = new this@NormalMemberImpl.permission = new
MemberPermissionChangeEvent(this@NormalMemberImpl, origin, new).broadcastWithBot(bot) MemberPermissionChangeEvent(this@NormalMemberImpl, origin, new).broadcast()
} }
} }
} }

View File

@ -27,7 +27,7 @@ private val ServerListSerializer: KSerializer<Set<ServerAddress>> =
SetSerializer(ServerAddress.serializer()) SetSerializer(ServerAddress.serializer())
internal interface BdhSessionSyncer { internal interface BdhSessionSyncer {
var bdhSession: CompletableDeferred<BdhSession> val bdhSession: CompletableDeferred<BdhSession>
val hasSession: Boolean val hasSession: Boolean
fun overrideSession( fun overrideSession(
@ -47,8 +47,9 @@ internal interface BdhSessionSyncer {
internal class BdhSessionSyncerImpl( internal class BdhSessionSyncerImpl(
private val configuration: BotConfiguration, private val configuration: BotConfiguration,
private val logger: MiraiLogger, private val logger: MiraiLogger,
private val componentStorage: ComponentStorage, private val context: ComponentStorage,
) : BdhSessionSyncer { ) : BdhSessionSyncer {
@Volatile
override var bdhSession: CompletableDeferred<BdhSession> = CompletableDeferred() override var bdhSession: CompletableDeferred<BdhSession> = CompletableDeferred()
override val hasSession: Boolean override val hasSession: Boolean
get() = kotlin.runCatching { bdhSession.getCompleted() }.isSuccess get() = kotlin.runCatching { bdhSession.getCompleted() }.isSuccess
@ -75,7 +76,7 @@ internal class BdhSessionSyncerImpl(
logger.verbose("Loading server list from cache.") logger.verbose("Loading server list from cache.")
kotlin.runCatching { kotlin.runCatching {
val list = JsonForCache.decodeFromString(ServerListSerializer, serverListCacheFile.readText()) val list = JsonForCache.decodeFromString(ServerListSerializer, serverListCacheFile.readText())
componentStorage[ServerList].setPreferred(list.map { ServerAddress(it.host, it.port) }) context[ServerList].setPreferred(list.map { ServerAddress(it.host, it.port) })
}.onFailure { }.onFailure {
logger.warning("Error in loading server list from cache", it) logger.warning("Error in loading server list from cache", it)
} }
@ -111,7 +112,7 @@ internal class BdhSessionSyncerImpl(
serverListCacheFile.writeText( serverListCacheFile.writeText(
JsonForCache.encodeToString( JsonForCache.encodeToString(
ServerListSerializer, ServerListSerializer,
componentStorage[ServerList].getPreferred() context[ServerList].getPreferred()
) )
) )
}.onFailure { }.onFailure {

View File

@ -70,7 +70,8 @@ internal class BotInitProcessorImpl(
// do them parallel. // do them parallel.
supervisorScope { supervisorScope {
// launch { syncMessageSvc() } launch { syncMessageSvc() }
launch { context[BdhSessionSyncer].loadFromCache() }
launch { context[OtherClientUpdater].update() } launch { context[OtherClientUpdater].update() }
launch { context[ContactUpdater].loadAll(registerResp.origin) } launch { context[ContactUpdater].loadAll(registerResp.origin) }
} }

View File

@ -18,7 +18,7 @@ import net.mamoe.mirai.event.ConcurrencyKind
import net.mamoe.mirai.event.EventPriority import net.mamoe.mirai.event.EventPriority
import net.mamoe.mirai.event.events.BotOfflineEvent import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.event.subscribeAlways import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.AbstractBot
import net.mamoe.mirai.internal.asQQAndroidBot import net.mamoe.mirai.internal.asQQAndroidBot
import net.mamoe.mirai.internal.network.component.ComponentKey import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.internal.network.handler.NetworkHandler import net.mamoe.mirai.internal.network.handler.NetworkHandler
@ -37,13 +37,13 @@ internal interface BotOfflineEventMonitor {
/** /**
* Attach a listener to the [scope]. [scope] is usually the scope of [NetworkHandler.State.OK]. * Attach a listener to the [scope]. [scope] is usually the scope of [NetworkHandler.State.OK].
*/ */
fun attachJob(bot: QQAndroidBot, scope: CoroutineScope) fun attachJob(bot: AbstractBot, scope: CoroutineScope)
} }
private data class BotClosedByEvent(val event: BotOfflineEvent) : RuntimeException("Bot is closed by event '$event'.") private data class BotClosedByEvent(val event: BotOfflineEvent) : RuntimeException("Bot is closed by event '$event'.")
internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor { internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor {
override fun attachJob(bot: QQAndroidBot, scope: CoroutineScope) { override fun attachJob(bot: AbstractBot, scope: CoroutineScope) {
bot.eventChannel.parentScope(scope).subscribeAlways( bot.eventChannel.parentScope(scope).subscribeAlways(
::onEvent, ::onEvent,
priority = EventPriority.MONITOR, priority = EventPriority.MONITOR,
@ -79,23 +79,17 @@ internal class BotOfflineEventMonitorImpl : BotOfflineEventMonitor {
is BotOfflineEvent.Force -> { is BotOfflineEvent.Force -> {
bot.logger.info { "Connection occupied by another android device: ${event.message}" } bot.logger.info { "Connection occupied by another android device: ${event.message}" }
closeNetwork() closeNetwork()
if (event.reconnect) {
bot.logger.info { "Reconnecting..." }
} else {
}
} }
is BotOfflineEvent.MsfOffline, is BotOfflineEvent.MsfOffline,
is BotOfflineEvent.Dropped, is BotOfflineEvent.Dropped,
is BotOfflineEvent.RequireReconnect, is BotOfflineEvent.RequireReconnect,
-> { -> {
// nothing to do val causeMessage = event.castOrNull<BotOfflineEvent.CauseAware>()?.cause?.toString() ?: event.toString()
bot.logger.info { "Connection lost, retrying login ($causeMessage)." }
} }
} }
if (event.reconnect) { if (event.reconnect) {
val causeMessage = event.castOrNull<BotOfflineEvent.CauseAware>()?.cause?.toString() ?: event.toString()
bot.logger.info { "Connection lost, retrying login ($causeMessage)." }
bot.launch { bot.launch {
val success: Boolean val success: Boolean
val time = measureTime { val time = measureTime {

View File

@ -20,9 +20,9 @@ import net.mamoe.mirai.internal.contact.replaceMagicCodes
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.internal.network.ParseErrorPacket import net.mamoe.mirai.internal.network.ParseErrorPacket
import net.mamoe.mirai.internal.network.component.ComponentKey import net.mamoe.mirai.internal.network.component.ComponentKey
import net.mamoe.mirai.internal.network.component.ComponentStorage import net.mamoe.mirai.internal.network.protocol.packet.*
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacket
import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.MiraiLogger
import net.mamoe.mirai.utils.cast
import net.mamoe.mirai.utils.verbose import net.mamoe.mirai.utils.verbose
internal interface PacketHandler { internal interface PacketHandler {
@ -32,11 +32,10 @@ internal interface PacketHandler {
} }
internal class PacketHandlerChain( internal class PacketHandlerChain(
private val instances: Collection<PacketHandler>, private val instances: Collection<PacketHandler>
primaryConstructorMark: Any?
) : PacketHandler { ) : PacketHandler {
constructor(vararg instances: PacketHandler?) : this(instances.filterNotNull(), null) constructor(vararg instances: PacketHandler?) : this(instances.filterNotNull())
constructor(instances: Iterable<PacketHandler?>) : this(instances.filterNotNull(), null) constructor(instances: Iterable<PacketHandler?>) : this(instances.filterNotNull())
override suspend fun handlePacket(incomingPacket: IncomingPacket) { override suspend fun handlePacket(incomingPacket: IncomingPacket) {
for (instance in instances) { for (instance in instances) {
@ -55,8 +54,7 @@ internal data class ExceptionInPacketHandlerException(
) : IllegalStateException("Exception in PacketHandler '$packetHandler'.") ) : IllegalStateException("Exception in PacketHandler '$packetHandler'.")
internal class LoggingPacketHandler( internal class LoggingPacketHandler(
val bot: QQAndroidBot, private val bot: QQAndroidBot,
val context: ComponentStorage,
private val logger: MiraiLogger, private val logger: MiraiLogger,
) : PacketHandler { ) : PacketHandler {
override suspend fun handlePacket(incomingPacket: IncomingPacket) { override suspend fun handlePacket(incomingPacket: IncomingPacket) {
@ -66,10 +64,10 @@ internal class LoggingPacketHandler(
packet is ParseErrorPacket -> { packet is ParseErrorPacket -> {
packet.direction.getLogger(bot).error(packet.error) packet.direction.getLogger(bot).error(packet.error)
} }
packet is MessageEvent -> packet.logMessageReceived()
packet is Packet.NoLog -> { packet is Packet.NoLog -> {
// nothing to do // nothing to do
} }
packet is MessageEvent -> packet.logMessageReceived()
packet is Event && packet !is Packet.NoEventLog -> bot.logger.verbose { packet is Event && packet !is Packet.NoEventLog -> bot.logger.verbose {
"Event: $packet".replaceMagicCodes() "Event: $packet".replaceMagicCodes()
} }
@ -81,8 +79,6 @@ internal class LoggingPacketHandler(
} }
internal class EventBroadcasterPacketHandler( internal class EventBroadcasterPacketHandler(
val bot: QQAndroidBot,
val context: ComponentStorage,
private val logger: MiraiLogger, private val logger: MiraiLogger,
) : PacketHandler { ) : PacketHandler {
@ -110,4 +106,26 @@ internal class EventBroadcasterPacketHandler(
} }
override fun toString(): String = "LoggingPacketHandler" override fun toString(): String = "LoggingPacketHandler"
}
internal class CallPacketFactoryPacketHandler(
private val bot: QQAndroidBot,
) : PacketHandler {
override suspend fun handlePacket(incomingPacket: IncomingPacket) {
val factory = KnownPacketFactories.findPacketFactory(incomingPacket.commandName) ?: return
factory.cast<PacketFactory<Packet?>>().run {
when (this) {
is IncomingPacketFactory -> {
val r = bot.handle(incomingPacket.data, incomingPacket.sequenceId)
if (r != null) {
bot.network.sendWithoutExpect(r)
}
}
is OutgoingPacketFactory -> bot.handle(incomingPacket.data)
}
}
}
override fun toString(): String = "CallPacketFactoryPacketHandler"
} }

View File

@ -39,7 +39,7 @@ import net.mamoe.mirai.utils.info
import net.mamoe.mirai.utils.withExceptionCollector import net.mamoe.mirai.utils.withExceptionCollector
/** /**
* Handles login, and acts also as a mediator of [BotInitProcessor], [] * Handles login, and acts also as a mediator of [BotInitProcessor]
*/ */
internal interface SsoProcessor { internal interface SsoProcessor {
val client: QQAndroidClient val client: QQAndroidClient
@ -108,6 +108,7 @@ internal class SsoProcessorImpl(
*/ */
@Throws(LoginFailedException::class) @Throws(LoginFailedException::class)
override suspend fun login(handler: NetworkHandler) = withExceptionCollector { override suspend fun login(handler: NetworkHandler) = withExceptionCollector {
ssoContext.bot.components[BdhSessionSyncer].loadServerListFromCache()
if (client.wLoginSigInfoInitialized) { if (client.wLoginSigInfoInitialized) {
kotlin.runCatching { kotlin.runCatching {
FastLoginImpl(handler).doLogin() FastLoginImpl(handler).doLogin()
@ -121,7 +122,7 @@ internal class SsoProcessorImpl(
} }
ssoContext.accountSecretsManager.saveSecrets(ssoContext.account, AccountSecretsImpl(client)) ssoContext.accountSecretsManager.saveSecrets(ssoContext.account, AccountSecretsImpl(client))
registerClientOnline(handler) registerClientOnline(handler)
ssoContext.bot.logger.info { "SSO login successful." } ssoContext.bot.logger.info { "Login successful." }
} }
private suspend fun registerClientOnline(handler: NetworkHandler): StatSvc.Register.Response { private suspend fun registerClientOnline(handler: NetworkHandler): StatSvc.Register.Response {

View File

@ -21,6 +21,7 @@ import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import java.util.concurrent.ConcurrentLinkedQueue import java.util.concurrent.ConcurrentLinkedQueue
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.reflect.KClass
/** /**
* Implements basic logics of [NetworkHandler] * Implements basic logics of [NetworkHandler]
@ -184,12 +185,16 @@ internal abstract class NetworkHandlerSupport(
val new: BaseStateImpl, val new: BaseStateImpl,
) : CancellationException("State is switched from $old to $new") ) : CancellationException("State is switched from $old to $new")
protected inline fun <reified S : BaseStateImpl> setState(noinline new: () -> S): S? = setState(S::class, new)
/** /**
* Calculate [new state][new] and set it as the current, returning the new state, or `null` if state has concurrently been set to CLOSED. * Calculate [new state][new] and set it as the current, returning the new state, or `null` if state has concurrently been set to CLOSED.
* *
* You may need to call [BaseStateImpl.resumeConnection] to activate the new state, as states are lazy. * You may need to call [BaseStateImpl.resumeConnection] to activate the new state, as states are lazy.
*/ */
protected fun <S : BaseStateImpl> setState(new: () -> S): S? = synchronized(this) { protected fun <S : BaseStateImpl> setState(newType: KClass<S>, new: () -> S): S? = synchronized(this) {
if (_state::class == newType) return@synchronized null // already set to expected state by another thread.
if (_state.correspondingState == NetworkHandler.State.CLOSED) return null // error("Cannot change state while it has already been CLOSED.") if (_state.correspondingState == NetworkHandler.State.CLOSED) return null // error("Cannot change state while it has already been CLOSED.")
val stateObserver = context.getOrNull(StateObserver) val stateObserver = context.getOrNull(StateObserver)

View File

@ -30,10 +30,7 @@ import net.mamoe.mirai.internal.network.handler.NetworkHandlerSupport
import net.mamoe.mirai.internal.network.handler.logger import net.mamoe.mirai.internal.network.handler.logger
import net.mamoe.mirai.internal.network.handler.state.StateObserver import net.mamoe.mirai.internal.network.handler.state.StateObserver
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacket
import net.mamoe.mirai.utils.ExceptionCollector import net.mamoe.mirai.utils.*
import net.mamoe.mirai.utils.childScope
import net.mamoe.mirai.utils.debug
import net.mamoe.mirai.utils.systemProp
import java.net.SocketAddress import java.net.SocketAddress
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import io.netty.channel.Channel as NettyChannel import io.netty.channel.Channel as NettyChannel
@ -218,7 +215,9 @@ internal open class NettyNetworkHandler(
context[SsoProcessor].login(this@NettyNetworkHandler) context[SsoProcessor].login(this@NettyNetworkHandler)
}.apply { }.apply {
invokeOnCompletion { error -> invokeOnCompletion { error ->
if (error != null) { if (error == null) {
this@NettyNetworkHandler.launch { resumeConnection() }
} else {
if (error is StateSwitchingException && error.new is StateConnecting) { if (error is StateSwitchingException && error.new is StateConnecting) {
return@invokeOnCompletion // already been switching to CONNECTING return@invokeOnCompletion // already been switching to CONNECTING
} }
@ -303,7 +302,7 @@ internal open class NettyNetworkHandler(
}.apply { }.apply {
invokeOnCompletion { e -> invokeOnCompletion { e ->
if (e != null) { if (e != null) {
logger.debug { "x" } logger.info { "Heartbeat failed: $e." }
} }
} }
} }

View File

@ -25,6 +25,7 @@ import net.mamoe.mirai.contact.NormalMember
import net.mamoe.mirai.data.MemberInfo import net.mamoe.mirai.data.MemberInfo
import net.mamoe.mirai.event.AbstractEvent import net.mamoe.mirai.event.AbstractEvent
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.contact.* import net.mamoe.mirai.internal.contact.*
@ -46,7 +47,6 @@ import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact import net.mamoe.mirai.internal.network.protocol.packet.chat.NewContact
import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList import net.mamoe.mirai.internal.network.protocol.packet.list.FriendList
import net.mamoe.mirai.internal.utils.broadcastWithBot
import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.writeProtoBuf
@ -203,7 +203,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
client, client,
MsgSvc.SyncFlag.CONTINUE, MsgSvc.SyncFlag.CONTINUE,
bot.client.syncingController.syncCookie bot.client.syncingController.syncCookie
).sendAndExpect<Packet>() ).sendAndExpect()
} }
return return
} }
@ -214,7 +214,7 @@ internal object MessageSvcPbGetMsg : OutgoingPacketFactory<MessageSvcPbGetMsg.Re
client, client,
MsgSvc.SyncFlag.CONTINUE, MsgSvc.SyncFlag.CONTINUE,
bot.client.syncingController.syncCookie bot.client.syncingController.syncCookie
).sendAndExpect<Packet>() ).sendAndExpect()
} }
return return
} }
@ -568,7 +568,7 @@ internal suspend fun MsgComm.Msg.transform(bot: QQAndroidBot, fromSync: Boolean
Mirai.newStranger(bot, StrangerInfoImpl(id, nick, fromGroup)).let { Mirai.newStranger(bot, StrangerInfoImpl(id, nick, fromGroup)).let {
bot.getStranger(id)?.let { previous -> bot.getStranger(id)?.let { previous ->
bot.strangers.remove(id) bot.strangers.remove(id)
StrangerRelationChangeEvent.Deleted(previous).broadcastWithBot(bot) StrangerRelationChangeEvent.Deleted(previous).broadcast()
} }
bot.strangers.delegate.add(it) bot.strangers.delegate.add(it)

View File

@ -15,6 +15,7 @@ import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.contact.Member import net.mamoe.mirai.contact.Member
import net.mamoe.mirai.event.AbstractEvent import net.mamoe.mirai.event.AbstractEvent
import net.mamoe.mirai.event.Event import net.mamoe.mirai.event.Event
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.GroupMessageEvent import net.mamoe.mirai.event.events.GroupMessageEvent
import net.mamoe.mirai.event.events.GroupMessageSyncEvent import net.mamoe.mirai.event.events.GroupMessageSyncEvent
import net.mamoe.mirai.event.events.MemberCardChangeEvent import net.mamoe.mirai.event.events.MemberCardChangeEvent
@ -33,9 +34,8 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.MsgComm
import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush import net.mamoe.mirai.internal.network.protocol.data.proto.MsgOnlinePush
import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0x8fc import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0x8fc
import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.IncomingPacketFactory
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.OnlinePushPbPushGroupMsg.MemberNick.Companion.generateMemberNickFromMember
import net.mamoe.mirai.internal.utils.broadcastWithBot
import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.network.protocol.packet.chat.receive.OnlinePushPbPushGroupMsg.MemberNick.Companion.generateMemberNickFromMember
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.message.data.MessageSourceKind.GROUP import net.mamoe.mirai.message.data.MessageSourceKind.GROUP
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
@ -162,14 +162,14 @@ internal object OnlinePushPbPushGroupMsg : IncomingPacketFactory<Packet?>("Onlin
new.nick.let { name -> new.nick.let { name ->
if (currentNameCard != name) { if (currentNameCard != name) {
sender._nameCard = name sender._nameCard = name
MemberCardChangeEvent(currentNameCard, name, sender).broadcastWithBot(sender.bot) MemberCardChangeEvent(currentNameCard, name, sender).broadcast()
} }
} }
} else { } else {
// 说明删除了群名片 // 说明删除了群名片
if (currentNameCard.isNotEmpty()) { if (currentNameCard.isNotEmpty()) {
sender._nameCard = "" sender._nameCard = ""
MemberCardChangeEvent(currentNameCard, "", sender).broadcastWithBot(sender.bot) MemberCardChangeEvent(currentNameCard, "", sender).broadcast()
} }
} }
} }

View File

@ -11,6 +11,7 @@ package net.mamoe.mirai.internal.network.protocol.packet.list
import kotlinx.io.core.ByteReadPacket import kotlinx.io.core.ByteReadPacket
import net.mamoe.mirai.contact.Stranger import net.mamoe.mirai.contact.Stranger
import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.StrangerRelationChangeEvent import net.mamoe.mirai.event.events.StrangerRelationChangeEvent
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
@ -20,7 +21,6 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.Oidb0x5d4
import net.mamoe.mirai.internal.network.protocol.data.proto.OidbSso import net.mamoe.mirai.internal.network.protocol.data.proto.OidbSso
import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory import net.mamoe.mirai.internal.network.protocol.packet.OutgoingPacketFactory
import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket import net.mamoe.mirai.internal.network.protocol.packet.buildOutgoingUniPacket
import net.mamoe.mirai.internal.utils.broadcastWithBot
import net.mamoe.mirai.internal.utils.io.serialization.loadAs import net.mamoe.mirai.internal.utils.io.serialization.loadAs
import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf import net.mamoe.mirai.internal.utils.io.serialization.readProtoBuf
import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.internal.utils.io.serialization.toByteArray
@ -96,7 +96,7 @@ internal class StrangerList {
pkg.bodybuffer.loadAs(Oidb0x5d4.RspBody.serializer()).result.forEach { delResult -> pkg.bodybuffer.loadAs(Oidb0x5d4.RspBody.serializer()).result.forEach { delResult ->
bot.getStranger(delResult.uin)?.let { bot.getStranger(delResult.uin)?.let {
bot.strangers.remove(delResult.uin) bot.strangers.remove(delResult.uin)
StrangerRelationChangeEvent.Deleted(it).broadcastWithBot(bot) StrangerRelationChangeEvent.Deleted(it).broadcast()
} }
} }
} }

View File

@ -16,10 +16,12 @@ import net.mamoe.mirai.internal.contact.replaceMagicCodes
import net.mamoe.mirai.internal.network.Packet import net.mamoe.mirai.internal.network.Packet
import net.mamoe.mirai.utils.verbose import net.mamoe.mirai.utils.verbose
@Deprecated("broad", ReplaceWith("this.broadcast()", "net.mamoe.mirai.event.broadcast"))
internal suspend fun <T : Event> T.broadcastWithBot(bot: Bot): T { internal suspend fun <T : Event> T.broadcastWithBot(bot: Bot): T {
this.let log@{ event -> this.let log@{ event ->
val logger = bot.logger val logger = bot.logger
if (event is Packet.NoLog) return@log if (event is Packet.NoLog) return@log
if (event is Packet.NoEventLog) return@log
if (event is Packet.NoEventLog) { if (event is Packet.NoEventLog) {
logger.verbose { "Recv: $event".replaceMagicCodes() } logger.verbose { "Recv: $event".replaceMagicCodes() }
} else { } else {

View File

@ -10,6 +10,7 @@
package net.mamoe.mirai.internal.network.framework package net.mamoe.mirai.internal.network.framework
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.internal.AbstractBot
import net.mamoe.mirai.internal.MockBot import net.mamoe.mirai.internal.MockBot
import net.mamoe.mirai.internal.QQAndroidBot import net.mamoe.mirai.internal.QQAndroidBot
import net.mamoe.mirai.internal.network.QQAndroidClient import net.mamoe.mirai.internal.network.QQAndroidClient
@ -109,13 +110,13 @@ internal abstract class AbstractRealNetworkHandlerTest<H : NetworkHandler> : Abs
set(ContactUpdater, ContactUpdaterImpl(bot, components, networkLogger)) set(ContactUpdater, ContactUpdaterImpl(bot, components, networkLogger))
set(BdhSessionSyncer, BdhSessionSyncerImpl(configuration, networkLogger, components)) set(BdhSessionSyncer, BdhSessionSyncerImpl(configuration, networkLogger, components))
set(ServerList, ServerListImpl()) set(ServerList, ServerListImpl())
set(PacketHandler, LoggingPacketHandler(bot, components, networkLogger)) set(PacketHandler, LoggingPacketHandler(bot, networkLogger))
set(PacketCodec, PacketCodecImpl()) set(PacketCodec, PacketCodecImpl())
set(OtherClientUpdater, OtherClientUpdaterImpl(bot, components, bot.logger)) set(OtherClientUpdater, OtherClientUpdaterImpl(bot, components, bot.logger))
set(ConfigPushSyncer, ConfigPushSyncerImpl()) set(ConfigPushSyncer, ConfigPushSyncerImpl())
set(BotOfflineEventMonitor, object : BotOfflineEventMonitor { set(BotOfflineEventMonitor, object : BotOfflineEventMonitor {
override fun attachJob(bot: QQAndroidBot, scope: CoroutineScope) { override fun attachJob(bot: AbstractBot, scope: CoroutineScope) {
} }
}) })
set(StateObserver, bot.run { stateObserverChain() }) set(StateObserver, bot.run { stateObserverChain() })