mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-05 00:10:13 +08:00
Fix #361
This commit is contained in:
parent
2dcd8ffea0
commit
2e8df632cd
@ -94,7 +94,7 @@ kotlin {
|
||||
val jvmMain by getting {
|
||||
dependencies {
|
||||
runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE
|
||||
// api(kotlinx("coroutines-debug", "1.3.5"))
|
||||
// api(kotlinx("coroutines-debug", Versions.Kotlin.coroutines))
|
||||
api("moe.him188:jcekt:${Versions.jcekt}")
|
||||
api(kotlinx("serialization-runtime", Versions.Kotlin.serialization))
|
||||
//api(kotlinx("serialization-protobuf", Versions.Kotlin.serialization))
|
||||
|
@ -7,13 +7,18 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("EXPERIMENTAL_API_USAGE", "DEPRECATION_ERROR", "OverridingDeprecatedMember", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
@file:Suppress(
|
||||
"EXPERIMENTAL_API_USAGE",
|
||||
"DEPRECATION_ERROR",
|
||||
"OverridingDeprecatedMember",
|
||||
"INVISIBLE_REFERENCE",
|
||||
"INVISIBLE_MEMBER"
|
||||
)
|
||||
|
||||
package net.mamoe.mirai.qqandroid
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.closeAndJoin
|
||||
import net.mamoe.mirai.event.Listener
|
||||
import net.mamoe.mirai.event.broadcast
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
@ -61,6 +66,10 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
if (event.bot != this@BotImpl) {
|
||||
return@subscribeAlways
|
||||
}
|
||||
if (!event.bot.isActive) {
|
||||
// bot closed
|
||||
return@subscribeAlways
|
||||
}
|
||||
if (!::_network.isInitialized) {
|
||||
// bot 还未登录就被 close
|
||||
return@subscribeAlways
|
||||
@ -79,6 +88,7 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
}
|
||||
bot.logger.info { "Connection dropped by server or lost, retrying login" }
|
||||
|
||||
var failed = false
|
||||
val time = measureTime {
|
||||
tailrec suspend fun reconnect() {
|
||||
retryCatching<Unit>(
|
||||
@ -95,26 +105,30 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
@OptIn(ThisApiMustBeUsedInWithConnectionLockBlock::class)
|
||||
relogin((event as? BotOfflineEvent.Dropped)?.cause)
|
||||
}
|
||||
BotReloginEvent(bot, (event as? BotOfflineEvent.Dropped)?.cause).broadcast()
|
||||
launch { BotReloginEvent(bot, (event as? BotOfflineEvent.Dropped)?.cause).broadcast() }
|
||||
return
|
||||
}.getOrElse {
|
||||
if (it is LoginFailedException && !it.killBot) {
|
||||
logger.info { "Cannot reconnect" }
|
||||
logger.info { "Cannot reconnect." }
|
||||
logger.warning(it)
|
||||
logger.info { "Retrying in 3s..." }
|
||||
delay(3000)
|
||||
return@getOrElse
|
||||
}
|
||||
logger.info { "Cannot reconnect" }
|
||||
throw it
|
||||
logger.info { "Cannot reconnect due to fatal error." }
|
||||
bot.cancel(CancellationException("Cannot reconnect due to fatal error.", it))
|
||||
failed = true
|
||||
return
|
||||
}
|
||||
reconnect()
|
||||
}
|
||||
reconnect()
|
||||
}
|
||||
|
||||
if (!failed) {
|
||||
logger.info { "Reconnected successfully in ${time.asHumanReadable}" }
|
||||
}
|
||||
}
|
||||
is BotOfflineEvent.Active -> {
|
||||
val cause = event.cause
|
||||
val msg = if (cause == null) {
|
||||
@ -122,12 +136,12 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
} else {
|
||||
" with exception: " + cause.message
|
||||
}
|
||||
bot.logger.info { "Bot is closed manually$msg" }
|
||||
closeAndJoin(CancellationException(event.toString()))
|
||||
bot.logger.info { "Bot is closed manually: $msg" }
|
||||
bot.cancel(CancellationException(event.toString()))
|
||||
}
|
||||
is BotOfflineEvent.Force -> {
|
||||
bot.logger.info { "Connection occupied by another android device: ${event.message}" }
|
||||
closeAndJoin(ForceOfflineException(event.toString()))
|
||||
bot.cancel(ForceOfflineException(event.toString()))
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -217,6 +231,8 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
|
||||
init {
|
||||
coroutineContext[Job]!!.invokeOnCompletion { throwable ->
|
||||
logger.info { "Bot cancelled" + throwable?.message?.let { ": $it" }.orEmpty() }
|
||||
|
||||
kotlin.runCatching {
|
||||
network.close(throwable)
|
||||
}
|
||||
@ -237,10 +253,12 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
// already cancelled
|
||||
return
|
||||
}
|
||||
this.launch {
|
||||
BotOfflineEvent.Active(this@BotImpl, cause).broadcast()
|
||||
GlobalScope.launch {
|
||||
runCatching { BotOfflineEvent.Active(this@BotImpl, cause).broadcast() }.exceptionOrNull()
|
||||
?.let { logger.error(it) }
|
||||
}
|
||||
logger.info { "Bot cancelled" + cause?.message?.let { ": $it" }.orEmpty() }
|
||||
|
||||
if (supervisorJob.isActive) {
|
||||
if (cause == null) {
|
||||
supervisorJob.cancel()
|
||||
} else {
|
||||
@ -248,6 +266,7 @@ internal abstract class BotImpl<N : BotNetworkHandler> constructor(
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
|
||||
internal annotation class ThisApiMustBeUsedInWithConnectionLockBlock
|
@ -123,7 +123,6 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
|
||||
channel.close()
|
||||
}
|
||||
channel = PlatformSocket()
|
||||
// TODO: 2020/2/14 连接多个服务器, #52
|
||||
|
||||
while (isActive) {
|
||||
try {
|
||||
|
@ -137,7 +137,10 @@ internal open class QQAndroidClient(
|
||||
return@retryCatching
|
||||
}.getOrElse {
|
||||
bot.client.serverList.remove(pair)
|
||||
if (it !is LoginFailedException) {
|
||||
// 不要重复打印.
|
||||
bot.logger.warning(it)
|
||||
}
|
||||
throw it
|
||||
}
|
||||
}.getOrElse {
|
||||
|
@ -50,7 +50,7 @@ suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() }
|
||||
abstract class Bot internal constructor(
|
||||
val configuration: BotConfiguration
|
||||
) : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI, ContactOrBot {
|
||||
final override val coroutineContext: CoroutineContext =
|
||||
final override val coroutineContext: CoroutineContext = // for id
|
||||
configuration.parentCoroutineContext
|
||||
.plus(SupervisorJob(configuration.parentCoroutineContext[Job]))
|
||||
.plus(configuration.parentCoroutineContext[CoroutineExceptionHandler]
|
||||
@ -58,6 +58,8 @@ abstract class Bot internal constructor(
|
||||
logger.error("An exception was thrown under a coroutine of Bot", e)
|
||||
}
|
||||
)
|
||||
.plus(CoroutineName("Mirai Bot"))
|
||||
|
||||
|
||||
companion object {
|
||||
@JvmField
|
||||
|
Loading…
Reference in New Issue
Block a user