From ae32536ed5c171a843af66aba7045e1f47c701fb Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 16 May 2020 14:29:03 +0800 Subject: [PATCH] Move `BotImpl` and `BotNetworkHandler` to mirai-core-qqandroid. --- .../net/mamoe/mirai/qqandroid}/BotImpl.kt | 62 ++++--------------- .../net/mamoe/mirai/qqandroid/contact/util.kt | 4 +- .../qqandroid}/network/BotNetworkHandler.kt | 16 +---- .../network/QQAndroidBotNetworkHandler.kt | 3 +- .../commonMain/kotlin/net.mamoe.mirai/Bot.kt | 36 ++++++----- .../net.mamoe.mirai/event/events/friend.kt | 3 +- .../net.mamoe.mirai/message/data/Image.kt | 5 +- .../qqandroid.network/Packet.kt | 3 + .../net.mamoe.mirai/utils/BotConfiguration.kt | 5 +- .../net/mamoe/mirai/BotJavaFriendlyAPI.kt | 6 +- 10 files changed, 54 insertions(+), 89 deletions(-) rename {mirai-core/src/commonMain/kotlin/net.mamoe.mirai => mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid}/BotImpl.kt (87%) rename {mirai-core/src/commonMain/kotlin/net.mamoe.mirai => mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid}/network/BotNetworkHandler.kt (88%) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt similarity index 87% rename from mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt rename to mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt index d1c1f5bb6..ffa2fecb5 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/BotImpl.kt @@ -7,31 +7,30 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -@file:Suppress("EXPERIMENTAL_API_USAGE", "DEPRECATION_ERROR", "OverridingDeprecatedMember") +@file:Suppress("EXPERIMENTAL_API_USAGE", "DEPRECATION_ERROR", "OverridingDeprecatedMember", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER") -package net.mamoe.mirai +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 import net.mamoe.mirai.event.events.BotReloginEvent import net.mamoe.mirai.event.subscribeAlways -import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.ForceOfflineException import net.mamoe.mirai.network.LoginFailedException -import net.mamoe.mirai.network.closeAndJoin +import net.mamoe.mirai.qqandroid.network.BotNetworkHandler +import net.mamoe.mirai.qqandroid.network.closeAndJoin +import net.mamoe.mirai.supervisorJob import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.internal.retryCatching import kotlin.coroutines.CoroutineContext import kotlin.time.ExperimentalTime import kotlin.time.measureTime -/* - * 泛型 N 不需要向外(接口)暴露. - */ -@MiraiInternalAPI -abstract class BotImpl constructor( +internal abstract class BotImpl constructor( context: Context, val configuration: BotConfiguration ) : Bot(), CoroutineScope { @@ -49,44 +48,9 @@ abstract class BotImpl constructor( final override val logger: MiraiLogger by lazy { configuration.botLoggerSupplier(this) } - init { - instances.addLast(this.weakRef()) - } - - companion object { - @PublishedApi - internal val instances: LockFreeLinkedList> = LockFreeLinkedList() - - fun forEachInstance(block: (Bot) -> Unit) = instances.forEach { - it.get()?.let(block) - } - - fun getInstance(qq: Long): Bot { - instances.forEach { - it.get()?.let { bot -> - if (bot.id == qq) { - return bot - } - } - } - throw NoSuchElementException(qq.toString()) - } - - fun getInstanceOrNull(qq: Long): Bot? { - instances.forEach { - it.get()?.let { bot -> - if (bot.id == qq) { - return bot - } - } - } - return null - } - } - // region network - final override val network: N get() = _network + val network: N get() = _network @Suppress("PropertyName") internal lateinit var _network: N @@ -160,10 +124,11 @@ abstract class BotImpl constructor( logger.info { "Reconnected successfully in ${time.asHumanReadable}" } } is BotOfflineEvent.Active -> { - val msg = if (event.cause == null) { + val cause = event.cause + val msg = if (cause == null) { "" } else { - " with exception: " + event.cause.message + " with exception: " + cause.message } bot.logger.info { "Bot is closed manually$msg" } closeAndJoin(CancellationException(event.toString())) @@ -175,6 +140,7 @@ abstract class BotImpl constructor( } } + /** * **Exposed public API** * [BotImpl.relogin] && [BotNetworkHandler.init] @@ -259,8 +225,6 @@ abstract class BotImpl constructor( init { coroutineContext[Job]!!.invokeOnCompletion { throwable -> - instances.removeIf { it.get()?.id == this.id } - network.close(throwable) offlineListener.cancel(CancellationException("Bot cancelled", throwable)) diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/util.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/util.kt index 800882390..fb38fa7b0 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/util.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/contact/util.kt @@ -22,7 +22,6 @@ import net.mamoe.mirai.qqandroid.asQQAndroidBot import net.mamoe.mirai.qqandroid.message.MessageSourceToFriendImpl import net.mamoe.mirai.qqandroid.message.ensureSequenceIdAvailable import net.mamoe.mirai.qqandroid.message.firstIsInstanceOrNull -import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler import net.mamoe.mirai.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg import net.mamoe.mirai.utils.verbose @@ -33,7 +32,8 @@ internal suspend fun Friend.sendMessageImpl(generic: T, message: M } event.message.firstIsInstanceOrNull()?.source?.ensureSequenceIdAvailable() lateinit var source: MessageSourceToFriendImpl - (bot.network as QQAndroidBotNetworkHandler).run { + val bot = bot.asQQAndroidBot() + bot.network.run { check( MessageSvcPbSendMsg.createToFriend( bot.asQQAndroidBot().client, diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/BotNetworkHandler.kt similarity index 88% rename from mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt rename to mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/BotNetworkHandler.kt index f0e624f74..2699a2104 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/BotNetworkHandler.kt @@ -9,7 +9,7 @@ @file:Suppress("EXPERIMENTAL_API_USAGE") -package net.mamoe.mirai.network +package net.mamoe.mirai.qqandroid.network import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CompletableJob @@ -40,17 +40,8 @@ import net.mamoe.mirai.utils.WeakRefProperty * * @suppress 此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告. */ -@MiraiInternalAPI @Suppress("PropertyName") -abstract class BotNetworkHandler : CoroutineScope { - - /* - 此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告. - 此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告. - 此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告. - */ - - +internal abstract class BotNetworkHandler : CoroutineScope { /** * 所属 [Bot]. 为弱引用 */ @@ -123,8 +114,7 @@ abstract class BotNetworkHandler : CoroutineScope { } } -@MiraiInternalAPI -suspend fun BotNetworkHandler.closeAndJoin(cause: Throwable? = null) { +internal suspend fun BotNetworkHandler.closeAndJoin(cause: Throwable? = null) { this.close(cause) this.supervisor.join() } \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt index 121831686..81b3cc36a 100644 --- a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -24,7 +24,6 @@ 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.message.MessageEvent -import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.UnsupportedSMSLoginException import net.mamoe.mirai.network.WrongPasswordException import net.mamoe.mirai.qqandroid.QQAndroidBot @@ -54,7 +53,7 @@ import kotlin.jvm.Volatile internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bot: QQAndroidBot) : BotNetworkHandler() { override val bot: QQAndroidBot by bot.unsafeWeakRef() override val supervisor: CompletableJob = SupervisorJob(coroutineContext[Job]) - override val logger: MiraiLogger get() = bot.configuration.networkLoggerSupplier(this) + override val logger: MiraiLogger get() = bot.configuration.networkLoggerSupplier(bot) override val coroutineContext: CoroutineContext = coroutineContext + CoroutineExceptionHandler { _, throwable -> logger.error("Exception in NetworkHandler", throwable) diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt index 3fce8c867..ff4ca556f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/Bot.kt @@ -21,7 +21,6 @@ import net.mamoe.mirai.event.events.MemberJoinRequestEvent import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.* -import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.network.LoginFailedException import net.mamoe.mirai.utils.* import kotlin.coroutines.CoroutineContext @@ -49,40 +48,56 @@ suspend inline fun B.alsoLogin(): B = also { login() } @Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_SUPER_CLASS") abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI, ContactOrBot { companion object { + @Suppress("ObjectPropertyName") + internal val _instances: LockFreeLinkedList> = LockFreeLinkedList() + /** * 复制一份此时的 [Bot] 实例列表. */ @PlannedRemoval("1.2.0") - @Deprecated("use botInstances instead", replaceWith = ReplaceWith("botInstances")) + @Deprecated( + "use botInstances instead", + replaceWith = ReplaceWith("botInstances"), + level = DeprecationLevel.ERROR + ) @JvmStatic val instances: List> - get() = BotImpl.instances.toList() + get() = _instances.toList() /** * 复制一份此时的 [Bot] 实例列表. */ @JvmStatic val botInstances: List - get() = BotImpl.instances.asSequence().mapNotNull { it.get() }.toList() + get() = _instances.asSequence().mapNotNull { it.get() }.toList() /** * 遍历每一个 [Bot] 实例 */ @JvmSynthetic - fun forEachInstance(block: (Bot) -> Unit) = BotImpl.forEachInstance(block) + fun forEachInstance(block: (Bot) -> Unit) = _instances.forEach { it.get()?.let(block) } /** * 获取一个 [Bot] 实例, 无对应实例时抛出 [NoSuchElementException] */ @JvmStatic @Throws(NoSuchElementException::class) - fun getInstance(qq: Long): Bot = BotImpl.getInstance(qq = qq) + fun getInstance(qq: Long): Bot = + getInstanceOrNull(qq) ?: throw NoSuchElementException(qq.toString()) /** * 获取一个 [Bot] 实例, 无对应实例时返回 `null` */ @JvmStatic - fun getInstanceOrNull(qq: Long): Bot? = BotImpl.getInstanceOrNull(qq = qq) + fun getInstanceOrNull(qq: Long): Bot? = + _instances.asSequence().mapNotNull { it.get() }.firstOrNull { it.id == qq } + } + + init { + _instances.addLast(this.weakRef()) + supervisorJob.invokeOnCompletion { + _instances.removeIf { it.get()?.id == this.id } + } } /** @@ -287,13 +302,6 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI, abstract fun close(cause: Throwable? = null) final override fun toString(): String = "Bot($id)" - - /** - * 网络模块. - * 此为内部 API: 它可能在任意时刻被改动. - */ - @MiraiInternalAPI - abstract val network: BotNetworkHandler } /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/friend.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/friend.kt index 429e2215d..fa4d5286f 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/friend.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/events/friend.kt @@ -9,7 +9,7 @@ @file:JvmMultifileClass @file:JvmName("BotEventsKt") -@file:Suppress("FunctionName") +@file:Suppress("FunctionName", "unused") package net.mamoe.mirai.event.events @@ -53,6 +53,7 @@ data class FriendDeleteEvent( /** * 一个账号请求添加机器人为好友的事件 */ +@Suppress("DEPRECATION") data class NewFriendRequestEvent( override val bot: Bot, /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt index d342384ef..70d11f4d1 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/message/data/Image.kt @@ -16,7 +16,6 @@ package net.mamoe.mirai.message.data import kotlinx.serialization.Serializable import net.mamoe.mirai.Bot -import net.mamoe.mirai.BotImpl import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Group import net.mamoe.mirai.utils.ExternalImage @@ -188,7 +187,7 @@ suspend fun Image.queryUrl(): String { @Suppress("DEPRECATION") return when (this) { is OnlineImage -> this.originUrl - else -> BotImpl.instances.peekFirst().get()?.queryImageUrl(this) + else -> Bot._instances.peekFirst().get()?.queryImageUrl(this) ?: error("No Bot available to query image url") } } @@ -243,7 +242,7 @@ interface OfflineImage : Image { ) @JvmSynthetic suspend fun OfflineImage.queryUrl(): String { - return BotImpl.instances.peekFirst().get()?.queryImageUrl(this) ?: error("No Bot available to query image url") + return Bot._instances.peekFirst().get()?.queryImageUrl(this) ?: error("No Bot available to query image url") } /** diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/qqandroid.network/Packet.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/qqandroid.network/Packet.kt index e2b8d5f23..787d5357d 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/qqandroid.network/Packet.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/qqandroid.network/Packet.kt @@ -1,11 +1,14 @@ package net.mamoe.mirai.qqandroid.network +import net.mamoe.mirai.utils.MiraiInternalAPI + /** * 从服务器收到的包解析之后的结构化数据. * 它是一个数据包工厂的处理的返回值. * * **InternalAPI**: 这是内部 API, 它随时都有可能被修改 */ +@MiraiInternalAPI interface Packet { /** * 实现这个接口的包将不会被记录到日志中 diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt index 51f3ba20c..1e7856816 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/utils/BotConfiguration.kt @@ -13,7 +13,6 @@ package net.mamoe.mirai.utils import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob import net.mamoe.mirai.Bot -import net.mamoe.mirai.network.BotNetworkHandler import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.coroutineContext @@ -33,7 +32,7 @@ open class BotConfiguration { * 网络层日志构造器 * @see noNetworkLog 不显示网络日志 */ - var networkLoggerSupplier: ((BotNetworkHandler) -> MiraiLogger) = { DefaultLogger("Network(${it.bot.id})") } + var networkLoggerSupplier: ((Bot) -> MiraiLogger) = { DefaultLogger("Network(${it.id})") } /** * 设备信息覆盖. 默认使用随机的设备信息. @@ -105,7 +104,7 @@ open class BotConfiguration { */ @ConfigurationDsl fun noNetworkLog() { - networkLoggerSupplier = { _: BotNetworkHandler -> SilentLogger } + networkLoggerSupplier = { _ -> SilentLogger } } /** diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotJavaFriendlyAPI.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotJavaFriendlyAPI.kt index 43b2350fd..b35f72596 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotJavaFriendlyAPI.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotJavaFriendlyAPI.kt @@ -6,6 +6,7 @@ import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageSource +import net.mamoe.mirai.message.data.queryUrl import net.mamoe.mirai.network.LoginFailedException import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiInternalAPI @@ -29,6 +30,7 @@ internal actual interface BotJavaFriendlyAPI { * * @throws LoginFailedException */ + @Throws(LoginFailedException::class) @JvmName("login") fun __loginBlockingForJava__() { runBlocking { login() } @@ -94,7 +96,7 @@ internal actual interface BotJavaFriendlyAPI { */ @JvmName("queryImageUrl") fun __queryImageUrlBlockingForJava__(image: Image): String { - return runBlocking { queryImageUrl(image) } + return runBlocking { image.queryUrl() } } /** @@ -134,7 +136,7 @@ internal actual interface BotJavaFriendlyAPI { */ @JvmName("queryImageUrlAsync") fun __queryImageUrlAsyncForJava__(image: Image): Future { - return future { queryImageUrl(image) } + return future { image.queryUrl() } } }