mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-23 10:20:14 +08:00
Fix the problem that login() function never returns
This commit is contained in:
parent
6296944419
commit
2a37904021
@ -17,6 +17,7 @@ import net.mamoe.mirai.utils.BotConfiguration
|
||||
import net.mamoe.mirai.utils.DefaultLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.internal.coerceAtLeastOrFail
|
||||
import net.mamoe.mirai.utils.io.logStacktrace
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.coroutineContext
|
||||
import kotlin.jvm.JvmOverloads
|
||||
@ -75,7 +76,8 @@ suspend inline fun Bot(qq: Long, password: String): Bot = Bot(qq.toUInt(), passw
|
||||
*/
|
||||
class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineContext) : CoroutineScope {
|
||||
private val supervisorJob = SupervisorJob(context[Job])
|
||||
override val coroutineContext: CoroutineContext = context + supervisorJob
|
||||
override val coroutineContext: CoroutineContext =
|
||||
context + supervisorJob + CoroutineExceptionHandler { _, e -> e.logStacktrace("An exception was thrown under a coroutine of Bot") }
|
||||
|
||||
constructor(qq: UInt, password: String, context: CoroutineContext) : this(BotAccount(qq, password), context)
|
||||
constructor(account: BotAccount, context: CoroutineContext) : this(account, DefaultLogger("Bot(" + account.id + ")"), context)
|
||||
@ -116,10 +118,10 @@ class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineCo
|
||||
* 然后重新启动并尝试登录
|
||||
*/
|
||||
@JvmOverloads // shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close
|
||||
fun reinitializeNetworkHandlerAsync(
|
||||
suspend fun reinitializeNetworkHandler(
|
||||
configuration: BotConfiguration,
|
||||
cause: Throwable? = null
|
||||
): Deferred<LoginResult> = async {
|
||||
): LoginResult {
|
||||
logger.info("Initializing BotNetworkHandler")
|
||||
try {
|
||||
if (::network.isInitialized) {
|
||||
@ -129,9 +131,20 @@ class Bot(val account: BotAccount, val logger: MiraiLogger, context: CoroutineCo
|
||||
logger.error("Cannot close network handler", e)
|
||||
}
|
||||
network = TIMBotNetworkHandler(coroutineContext + configuration, this@Bot)
|
||||
network.login()
|
||||
|
||||
return network.login()
|
||||
}
|
||||
|
||||
/**
|
||||
* [关闭][BotNetworkHandler.close]网络处理器, 取消所有运行在 [BotNetworkHandler] 下的协程.
|
||||
* 然后重新启动并尝试登录
|
||||
*/
|
||||
@JvmOverloads // shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close
|
||||
fun reinitializeNetworkHandlerAsync(
|
||||
configuration: BotConfiguration,
|
||||
cause: Throwable? = null
|
||||
): Deferred<LoginResult> = async { reinitializeNetworkHandler(configuration, cause) }
|
||||
|
||||
/**
|
||||
* Bot 联系人管理.
|
||||
*
|
||||
|
@ -70,13 +70,13 @@ suspend inline fun Bot.login(noinline configuration: BotConfiguration.() -> Unit
|
||||
contract {
|
||||
callsInPlace(configuration, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
return this.reinitializeNetworkHandlerAsync(BotConfiguration().apply(configuration)).await()
|
||||
return this.reinitializeNetworkHandler(BotConfiguration().apply(configuration))
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用默认的配置 ([BotConfiguration.Default]) 登录, 返回登录结果
|
||||
*/
|
||||
suspend inline fun Bot.login(): LoginResult = this.reinitializeNetworkHandlerAsync(BotConfiguration.Default).await()
|
||||
suspend inline fun Bot.login(): LoginResult = this.reinitializeNetworkHandler(BotConfiguration.Default)
|
||||
|
||||
/**
|
||||
* 使用默认的配置 ([BotConfiguration.Default]) 登录, 返回 [this]
|
||||
@ -91,7 +91,7 @@ suspend inline fun Bot.alsoLogin(noinline configuration: BotConfiguration.() ->
|
||||
contract {
|
||||
callsInPlace(configuration, InvocationKind.EXACTLY_ONCE)
|
||||
}
|
||||
this.reinitializeNetworkHandlerAsync(BotConfiguration().apply(configuration)).await().requireSuccess()
|
||||
this.reinitializeNetworkHandler(BotConfiguration().apply(configuration)).requireSuccess()
|
||||
return this
|
||||
}
|
||||
|
||||
|
@ -58,8 +58,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
|
||||
private var heartbeatJob: Job? = null
|
||||
|
||||
private lateinit var userContext: CoroutineContext
|
||||
|
||||
override suspend fun addHandler(temporaryPacketHandler: TemporaryPacketHandler<*, *>) {
|
||||
handlersLock.withLock {
|
||||
temporaryPacketHandlers.add(temporaryPacketHandler)
|
||||
@ -68,7 +66,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
}
|
||||
|
||||
override suspend fun login(): LoginResult {
|
||||
userContext = coroutineContext
|
||||
return withContext(this.coroutineContext) {
|
||||
TIMProtocol.SERVER_IP.sortedBy { Random.nextInt() }.forEach { ip ->
|
||||
bot.logger.info("Connecting server $ip")
|
||||
@ -97,10 +94,6 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
override lateinit var session: BotSession
|
||||
|
||||
//private | internal
|
||||
private fun onLoggedIn() {
|
||||
session = BotSession(sessionKey, socket)
|
||||
bot.logger.info("Successfully logged in")
|
||||
}
|
||||
|
||||
private var sessionKey: SessionKey by Delegates.notNull()
|
||||
|
||||
@ -379,12 +372,10 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
}
|
||||
|
||||
is TouchPacket.TouchResponse.Redirection -> {
|
||||
withContext(userContext) {
|
||||
socket.close()
|
||||
bot.logger.info("Redirecting to ${packet.serverIP}")
|
||||
socket = BotSocketAdapter(packet.serverIP!!)
|
||||
loginResult.complete(socket.resendTouch())
|
||||
}
|
||||
socket.close()
|
||||
bot.logger.info("Redirecting to ${packet.serverIP}")
|
||||
socket = BotSocketAdapter(packet.serverIP!!)
|
||||
loginResult.complete(socket.resendTouch())
|
||||
}
|
||||
|
||||
is SubmitPasswordPacket.LoginResponse.Failed -> {
|
||||
@ -417,14 +408,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
|
||||
if (packet.unknownBoolean) {
|
||||
this.captchaSectionId = 1
|
||||
socket.sendPacket(
|
||||
CaptchaPacket.RequestTransmission(
|
||||
bot.qqAccount,
|
||||
this.token0825,
|
||||
this.captchaSectionId++,
|
||||
packet.token00BA
|
||||
)
|
||||
)
|
||||
socket.sendPacket(CaptchaPacket.RequestTransmission(bot.qqAccount, this.token0825, this.captchaSectionId++, packet.token00BA))
|
||||
}
|
||||
}
|
||||
|
||||
@ -457,17 +441,13 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
socket.sendPacket(CaptchaPacket.Submit(bot.qqAccount, token0825, code, packet.captchaToken))
|
||||
}
|
||||
} else {
|
||||
socket.sendPacket(
|
||||
CaptchaPacket.RequestTransmission(bot.qqAccount, token0825, captchaSectionId++, packet.token00BA)
|
||||
)
|
||||
socket.sendPacket(CaptchaPacket.RequestTransmission(bot.qqAccount, token0825, captchaSectionId++, packet.token00BA))
|
||||
}
|
||||
}
|
||||
|
||||
is SubmitPasswordPacket.LoginResponse.Success -> {
|
||||
this.sessionResponseDecryptionKey = packet.sessionResponseDecryptionKey
|
||||
socket.sendPacket(
|
||||
RequestSessionPacket(bot.qqAccount, socket.serverIp, packet.token38, packet.token88, packet.encryptionKey)
|
||||
)
|
||||
socket.sendPacket(RequestSessionPacket(bot.qqAccount, socket.serverIp, packet.token38, packet.token88, packet.encryptionKey))
|
||||
}
|
||||
|
||||
//是ClientPasswordSubmissionPacket之后服务器回复的可能之一
|
||||
@ -493,6 +473,15 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
sessionKey = packet.sessionKey
|
||||
bot.logger.info("sessionKey = ${sessionKey.value.toUHexString()}")
|
||||
|
||||
setOnlineStatus(OnlineStatus.ONLINE)//required
|
||||
}
|
||||
|
||||
is ChangeOnlineStatusPacket.ChangeOnlineStatusResponse -> {
|
||||
BotLoginSucceedEvent(bot).broadcast()
|
||||
|
||||
|
||||
session = BotSession(sessionKey, socket)
|
||||
|
||||
val configuration = currentBotConfiguration()
|
||||
heartbeatJob = this@TIMBotNetworkHandler.launch {
|
||||
while (socket.isOpen) {
|
||||
@ -514,15 +503,8 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou
|
||||
}
|
||||
}
|
||||
|
||||
bot.logger.info("Successfully logged in")
|
||||
loginResult.complete(LoginResult.SUCCESS)
|
||||
|
||||
setOnlineStatus(OnlineStatus.ONLINE)//required
|
||||
}
|
||||
|
||||
is ChangeOnlineStatusPacket.ChangeOnlineStatusResponse -> {
|
||||
BotLoginSucceedEvent(bot).broadcast()
|
||||
|
||||
onLoggedIn()
|
||||
this.close()//The LoginHandler is useless since then
|
||||
}
|
||||
}
|
||||
|
@ -113,7 +113,8 @@ inline fun LoginResult.requireSuccess(lazyMessage: (LoginResult) -> String) {
|
||||
* 检查 [this] 为 [LoginResult.SUCCESS].
|
||||
* 失败则 [error]
|
||||
*/
|
||||
fun LoginResult.requireSuccess() = requireSuccess { "Login failed: $this" }
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun LoginResult.requireSuccess() = requireSuccess { "Login failed: $this" }
|
||||
|
||||
/**
|
||||
* 检查 [this] 为 [LoginResult.SUCCESS].
|
||||
@ -121,7 +122,8 @@ fun LoginResult.requireSuccess() = requireSuccess { "Login failed: $this" }
|
||||
*
|
||||
* @return 成功时 [Unit], 失败时 `null`
|
||||
*/
|
||||
fun LoginResult.requireSuccessOrNull(): Unit? = if (this == SUCCESS) Unit else null
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
inline fun LoginResult.requireSuccessOrNull(): Unit? = if (this == SUCCESS) Unit else null
|
||||
|
||||
/**
|
||||
* 返回 [this] 是否为 [LoginResult.SUCCESS].
|
||||
|
@ -12,6 +12,7 @@ internal object DebugLogger : MiraiLogger by DefaultLogger("Packet Debug")
|
||||
|
||||
internal fun Throwable.logStacktrace(message: String? = null) = DebugLogger.error(message, this)
|
||||
|
||||
@PublishedApi
|
||||
internal fun debugPrintln(any: Any?) = DebugLogger.debug(any)
|
||||
|
||||
@Deprecated("Low efficiency, only for debug purpose", ReplaceWith("this"))
|
||||
|
Loading…
Reference in New Issue
Block a user