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