Преглед изворни кода

Move `BotImpl` and `BotNetworkHandler` to mirai-core-qqandroid.

Him188 пре 5 година
родитељ
комит
ae32536ed5

+ 13 - 49
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt → 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<N : BotNetworkHandler> constructor(
+internal abstract class BotImpl<N : BotNetworkHandler> constructor(
     context: Context,
     val configuration: BotConfiguration
 ) : Bot(), CoroutineScope {
@@ -49,44 +48,9 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
 
     final override val logger: MiraiLogger by lazy { configuration.botLoggerSupplier(this) }
 
-    init {
-        instances.addLast(this.weakRef())
-    }
-
-    companion object {
-        @PublishedApi
-        internal val instances: LockFreeLinkedList<WeakRef<Bot>> = 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<N : BotNetworkHandler> 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<N : BotNetworkHandler> constructor(
             }
         }
 
+
     /**
      * **Exposed public API**
      * [BotImpl.relogin] && [BotNetworkHandler.init]
@@ -259,8 +225,6 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
 
     init {
         coroutineContext[Job]!!.invokeOnCompletion { throwable ->
-            instances.removeIf { it.get()?.id == this.id }
-
             network.close(throwable)
             offlineListener.cancel(CancellationException("Bot cancelled", throwable))
 

+ 2 - 2
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 <T : Contact> Friend.sendMessageImpl(generic: T, message: M
     }
     event.message.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
     lateinit var source: MessageSourceToFriendImpl
-    (bot.network as QQAndroidBotNetworkHandler).run {
+    val bot = bot.asQQAndroidBot()
+    bot.network.run {
         check(
             MessageSvcPbSendMsg.createToFriend(
                 bot.asQQAndroidBot().client,

+ 3 - 13
mirai-core/src/commonMain/kotlin/net.mamoe.mirai/network/BotNetworkHandler.kt → 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()
 }

+ 1 - 2
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)

+ 22 - 14
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 : Bot> 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<WeakRef<Bot>> = 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<WeakRef<Bot>>
-            get() = BotImpl.instances.toList()
+            get() = _instances.toList()
 
         /**
          * 复制一份此时的 [Bot] 实例列表.
          */
         @JvmStatic
         val botInstances: List<Bot>
-            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
 }
 
 /**

+ 2 - 1
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,
     /**

+ 2 - 3
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")
 }
 
 /**

+ 3 - 0
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 {
     /**
      * 实现这个接口的包将不会被记录到日志中

+ 2 - 3
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 }
     }
 
     /**

+ 4 - 2
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<String> {
-        return future { queryImageUrl(image) }
+        return future { image.queryUrl() }
     }
 }