Commit ae32536e authored by Him188's avatar Him188

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

parent 84c47c9f
...@@ -7,31 +7,30 @@ ...@@ -7,31 +7,30 @@
* https://github.com/mamoe/mirai/blob/master/LICENSE * 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 kotlinx.coroutines.*
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
import net.mamoe.mirai.event.events.BotReloginEvent import net.mamoe.mirai.event.events.BotReloginEvent
import net.mamoe.mirai.event.subscribeAlways import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.ForceOfflineException import net.mamoe.mirai.network.ForceOfflineException
import net.mamoe.mirai.network.LoginFailedException 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.*
import net.mamoe.mirai.utils.internal.retryCatching import net.mamoe.mirai.utils.internal.retryCatching
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.time.ExperimentalTime import kotlin.time.ExperimentalTime
import kotlin.time.measureTime import kotlin.time.measureTime
/* internal abstract class BotImpl<N : BotNetworkHandler> constructor(
* 泛型 N 不需要向外(接口)暴露.
*/
@MiraiInternalAPI
abstract class BotImpl<N : BotNetworkHandler> constructor(
context: Context, context: Context,
val configuration: BotConfiguration val configuration: BotConfiguration
) : Bot(), CoroutineScope { ) : Bot(), CoroutineScope {
...@@ -49,44 +48,9 @@ abstract class BotImpl<N : BotNetworkHandler> constructor( ...@@ -49,44 +48,9 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
final override val logger: MiraiLogger by lazy { configuration.botLoggerSupplier(this) } 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 // region network
final override val network: N get() = _network val network: N get() = _network
@Suppress("PropertyName") @Suppress("PropertyName")
internal lateinit var _network: N internal lateinit var _network: N
...@@ -160,10 +124,11 @@ abstract class BotImpl<N : BotNetworkHandler> constructor( ...@@ -160,10 +124,11 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
logger.info { "Reconnected successfully in ${time.asHumanReadable}" } logger.info { "Reconnected successfully in ${time.asHumanReadable}" }
} }
is BotOfflineEvent.Active -> { is BotOfflineEvent.Active -> {
val msg = if (event.cause == null) { val cause = event.cause
val msg = if (cause == null) {
"" ""
} else { } else {
" with exception: " + event.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())) closeAndJoin(CancellationException(event.toString()))
...@@ -175,6 +140,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor( ...@@ -175,6 +140,7 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
} }
} }
/** /**
* **Exposed public API** * **Exposed public API**
* [BotImpl.relogin] && [BotNetworkHandler.init] * [BotImpl.relogin] && [BotNetworkHandler.init]
...@@ -259,8 +225,6 @@ abstract class BotImpl<N : BotNetworkHandler> constructor( ...@@ -259,8 +225,6 @@ abstract class BotImpl<N : BotNetworkHandler> constructor(
init { init {
coroutineContext[Job]!!.invokeOnCompletion { throwable -> coroutineContext[Job]!!.invokeOnCompletion { throwable ->
instances.removeIf { it.get()?.id == this.id }
network.close(throwable) network.close(throwable)
offlineListener.cancel(CancellationException("Bot cancelled", throwable)) offlineListener.cancel(CancellationException("Bot cancelled", throwable))
......
...@@ -22,7 +22,6 @@ import net.mamoe.mirai.qqandroid.asQQAndroidBot ...@@ -22,7 +22,6 @@ import net.mamoe.mirai.qqandroid.asQQAndroidBot
import net.mamoe.mirai.qqandroid.message.MessageSourceToFriendImpl import net.mamoe.mirai.qqandroid.message.MessageSourceToFriendImpl
import net.mamoe.mirai.qqandroid.message.ensureSequenceIdAvailable import net.mamoe.mirai.qqandroid.message.ensureSequenceIdAvailable
import net.mamoe.mirai.qqandroid.message.firstIsInstanceOrNull 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.qqandroid.network.protocol.packet.chat.receive.MessageSvcPbSendMsg
import net.mamoe.mirai.utils.verbose import net.mamoe.mirai.utils.verbose
...@@ -33,7 +32,8 @@ internal suspend fun <T : Contact> Friend.sendMessageImpl(generic: T, message: M ...@@ -33,7 +32,8 @@ internal suspend fun <T : Contact> Friend.sendMessageImpl(generic: T, message: M
} }
event.message.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable() event.message.firstIsInstanceOrNull<QuoteReply>()?.source?.ensureSequenceIdAvailable()
lateinit var source: MessageSourceToFriendImpl lateinit var source: MessageSourceToFriendImpl
(bot.network as QQAndroidBotNetworkHandler).run { val bot = bot.asQQAndroidBot()
bot.network.run {
check( check(
MessageSvcPbSendMsg.createToFriend( MessageSvcPbSendMsg.createToFriend(
bot.asQQAndroidBot().client, bot.asQQAndroidBot().client,
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
@file:Suppress("EXPERIMENTAL_API_USAGE") @file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.network package net.mamoe.mirai.qqandroid.network
import kotlinx.coroutines.CancellationException import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.CompletableJob import kotlinx.coroutines.CompletableJob
...@@ -40,17 +40,8 @@ import net.mamoe.mirai.utils.WeakRefProperty ...@@ -40,17 +40,8 @@ import net.mamoe.mirai.utils.WeakRefProperty
* *
* @suppress 此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告. * @suppress 此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告.
*/ */
@MiraiInternalAPI
@Suppress("PropertyName") @Suppress("PropertyName")
abstract class BotNetworkHandler : CoroutineScope { internal abstract class BotNetworkHandler : CoroutineScope {
/*
此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告.
此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告.
此为**内部 API**, 可能在任意时刻被改动, 且不会给出任何警告.
*/
/** /**
* 所属 [Bot]. 为弱引用 * 所属 [Bot]. 为弱引用
*/ */
...@@ -123,8 +114,7 @@ abstract class BotNetworkHandler : CoroutineScope { ...@@ -123,8 +114,7 @@ abstract class BotNetworkHandler : CoroutineScope {
} }
} }
@MiraiInternalAPI internal suspend fun BotNetworkHandler.closeAndJoin(cause: Throwable? = null) {
suspend fun BotNetworkHandler.closeAndJoin(cause: Throwable? = null) {
this.close(cause) this.close(cause)
this.supervisor.join() this.supervisor.join()
} }
\ No newline at end of file
...@@ -24,7 +24,6 @@ import net.mamoe.mirai.event.events.BotOfflineEvent ...@@ -24,7 +24,6 @@ import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.event.events.BotOnlineEvent import net.mamoe.mirai.event.events.BotOnlineEvent
import net.mamoe.mirai.event.events.BotReloginEvent import net.mamoe.mirai.event.events.BotReloginEvent
import net.mamoe.mirai.message.MessageEvent import net.mamoe.mirai.message.MessageEvent
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.UnsupportedSMSLoginException import net.mamoe.mirai.network.UnsupportedSMSLoginException
import net.mamoe.mirai.network.WrongPasswordException import net.mamoe.mirai.network.WrongPasswordException
import net.mamoe.mirai.qqandroid.QQAndroidBot import net.mamoe.mirai.qqandroid.QQAndroidBot
...@@ -54,7 +53,7 @@ import kotlin.jvm.Volatile ...@@ -54,7 +53,7 @@ import kotlin.jvm.Volatile
internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bot: QQAndroidBot) : BotNetworkHandler() { internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bot: QQAndroidBot) : BotNetworkHandler() {
override val bot: QQAndroidBot by bot.unsafeWeakRef() override val bot: QQAndroidBot by bot.unsafeWeakRef()
override val supervisor: CompletableJob = SupervisorJob(coroutineContext[Job]) 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 -> override val coroutineContext: CoroutineContext = coroutineContext + CoroutineExceptionHandler { _, throwable ->
logger.error("Exception in NetworkHandler", throwable) logger.error("Exception in NetworkHandler", throwable)
......
...@@ -21,7 +21,6 @@ import net.mamoe.mirai.event.events.MemberJoinRequestEvent ...@@ -21,7 +21,6 @@ import net.mamoe.mirai.event.events.MemberJoinRequestEvent
import net.mamoe.mirai.event.events.NewFriendRequestEvent import net.mamoe.mirai.event.events.NewFriendRequestEvent
import net.mamoe.mirai.message.MessageReceipt import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.* import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.network.BotNetworkHandler
import net.mamoe.mirai.network.LoginFailedException import net.mamoe.mirai.network.LoginFailedException
import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.*
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
...@@ -49,40 +48,56 @@ suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() } ...@@ -49,40 +48,56 @@ suspend inline fun <B : Bot> B.alsoLogin(): B = also { login() }
@Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_SUPER_CLASS") @Suppress("INAPPLICABLE_JVM_NAME", "EXPOSED_SUPER_CLASS")
abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI, ContactOrBot { abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI, ContactOrBot {
companion object { companion object {
@Suppress("ObjectPropertyName")
internal val _instances: LockFreeLinkedList<WeakRef<Bot>> = LockFreeLinkedList()
/** /**
* 复制一份此时的 [Bot] 实例列表. * 复制一份此时的 [Bot] 实例列表.
*/ */
@PlannedRemoval("1.2.0") @PlannedRemoval("1.2.0")
@Deprecated("use botInstances instead", replaceWith = ReplaceWith("botInstances")) @Deprecated(
"use botInstances instead",
replaceWith = ReplaceWith("botInstances"),
level = DeprecationLevel.ERROR
)
@JvmStatic @JvmStatic
val instances: List<WeakRef<Bot>> val instances: List<WeakRef<Bot>>
get() = BotImpl.instances.toList() get() = _instances.toList()
/** /**
* 复制一份此时的 [Bot] 实例列表. * 复制一份此时的 [Bot] 实例列表.
*/ */
@JvmStatic @JvmStatic
val botInstances: List<Bot> val botInstances: List<Bot>
get() = BotImpl.instances.asSequence().mapNotNull { it.get() }.toList() get() = _instances.asSequence().mapNotNull { it.get() }.toList()
/** /**
* 遍历每一个 [Bot] 实例 * 遍历每一个 [Bot] 实例
*/ */
@JvmSynthetic @JvmSynthetic
fun forEachInstance(block: (Bot) -> Unit) = BotImpl.forEachInstance(block) fun forEachInstance(block: (Bot) -> Unit) = _instances.forEach { it.get()?.let(block) }
/** /**
* 获取一个 [Bot] 实例, 无对应实例时抛出 [NoSuchElementException] * 获取一个 [Bot] 实例, 无对应实例时抛出 [NoSuchElementException]
*/ */
@JvmStatic @JvmStatic
@Throws(NoSuchElementException::class) @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` * 获取一个 [Bot] 实例, 无对应实例时返回 `null`
*/ */
@JvmStatic @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, ...@@ -287,13 +302,6 @@ abstract class Bot : CoroutineScope, LowLevelBotAPIAccessor, BotJavaFriendlyAPI,
abstract fun close(cause: Throwable? = null) abstract fun close(cause: Throwable? = null)
final override fun toString(): String = "Bot($id)" final override fun toString(): String = "Bot($id)"
/**
* 网络模块.
* 此为内部 API: 它可能在任意时刻被改动.
*/
@MiraiInternalAPI
abstract val network: BotNetworkHandler
} }
/** /**
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
@file:JvmMultifileClass @file:JvmMultifileClass
@file:JvmName("BotEventsKt") @file:JvmName("BotEventsKt")
@file:Suppress("FunctionName") @file:Suppress("FunctionName", "unused")
package net.mamoe.mirai.event.events package net.mamoe.mirai.event.events
...@@ -53,6 +53,7 @@ data class FriendDeleteEvent( ...@@ -53,6 +53,7 @@ data class FriendDeleteEvent(
/** /**
* 一个账号请求添加机器人为好友的事件 * 一个账号请求添加机器人为好友的事件
*/ */
@Suppress("DEPRECATION")
data class NewFriendRequestEvent( data class NewFriendRequestEvent(
override val bot: Bot, override val bot: Bot,
/** /**
......
...@@ -16,7 +16,6 @@ package net.mamoe.mirai.message.data ...@@ -16,7 +16,6 @@ package net.mamoe.mirai.message.data
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.BotImpl
import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.contact.Contact
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.utils.ExternalImage import net.mamoe.mirai.utils.ExternalImage
...@@ -188,7 +187,7 @@ suspend fun Image.queryUrl(): String { ...@@ -188,7 +187,7 @@ suspend fun Image.queryUrl(): String {
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
return when (this) { return when (this) {
is OnlineImage -> this.originUrl 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") ?: error("No Bot available to query image url")
} }
} }
...@@ -243,7 +242,7 @@ interface OfflineImage : Image { ...@@ -243,7 +242,7 @@ interface OfflineImage : Image {
) )
@JvmSynthetic @JvmSynthetic
suspend fun OfflineImage.queryUrl(): String { 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")
} }
/** /**
......
package net.mamoe.mirai.qqandroid.network package net.mamoe.mirai.qqandroid.network
import net.mamoe.mirai.utils.MiraiInternalAPI
/** /**
* 从服务器收到的包解析之后的结构化数据. * 从服务器收到的包解析之后的结构化数据.
* 它是一个数据包工厂的处理的返回值. * 它是一个数据包工厂的处理的返回值.
* *
* **InternalAPI**: 这是内部 API, 它随时都有可能被修改 * **InternalAPI**: 这是内部 API, 它随时都有可能被修改
*/ */
@MiraiInternalAPI
interface Packet { interface Packet {
/** /**
* 实现这个接口的包将不会被记录到日志中 * 实现这个接口的包将不会被记录到日志中
......
...@@ -13,7 +13,6 @@ package net.mamoe.mirai.utils ...@@ -13,7 +13,6 @@ package net.mamoe.mirai.utils
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob import kotlinx.coroutines.SupervisorJob
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.network.BotNetworkHandler
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
import kotlin.coroutines.EmptyCoroutineContext import kotlin.coroutines.EmptyCoroutineContext
import kotlin.coroutines.coroutineContext import kotlin.coroutines.coroutineContext
...@@ -33,7 +32,7 @@ open class BotConfiguration { ...@@ -33,7 +32,7 @@ open class BotConfiguration {
* 网络层日志构造器 * 网络层日志构造器
* @see noNetworkLog 不显示网络日志 * @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 { ...@@ -105,7 +104,7 @@ open class BotConfiguration {
*/ */
@ConfigurationDsl @ConfigurationDsl
fun noNetworkLog() { fun noNetworkLog() {
networkLoggerSupplier = { _: BotNetworkHandler -> SilentLogger } networkLoggerSupplier = { _ -> SilentLogger }
} }
/** /**
......
...@@ -6,6 +6,7 @@ import net.mamoe.mirai.message.MessageReceipt ...@@ -6,6 +6,7 @@ import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.Image import net.mamoe.mirai.message.data.Image
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
import net.mamoe.mirai.message.data.MessageSource import net.mamoe.mirai.message.data.MessageSource
import net.mamoe.mirai.message.data.queryUrl
import net.mamoe.mirai.network.LoginFailedException import net.mamoe.mirai.network.LoginFailedException
import net.mamoe.mirai.utils.MiraiExperimentalAPI import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.MiraiInternalAPI import net.mamoe.mirai.utils.MiraiInternalAPI
...@@ -29,6 +30,7 @@ internal actual interface BotJavaFriendlyAPI { ...@@ -29,6 +30,7 @@ internal actual interface BotJavaFriendlyAPI {
* *
* @throws LoginFailedException * @throws LoginFailedException
*/ */
@Throws(LoginFailedException::class)
@JvmName("login") @JvmName("login")
fun __loginBlockingForJava__() { fun __loginBlockingForJava__() {
runBlocking { login() } runBlocking { login() }
...@@ -94,7 +96,7 @@ internal actual interface BotJavaFriendlyAPI { ...@@ -94,7 +96,7 @@ internal actual interface BotJavaFriendlyAPI {
*/ */
@JvmName("queryImageUrl") @JvmName("queryImageUrl")
fun __queryImageUrlBlockingForJava__(image: Image): String { fun __queryImageUrlBlockingForJava__(image: Image): String {
return runBlocking { queryImageUrl(image) } return runBlocking { image.queryUrl() }
} }
/** /**
...@@ -134,7 +136,7 @@ internal actual interface BotJavaFriendlyAPI { ...@@ -134,7 +136,7 @@ internal actual interface BotJavaFriendlyAPI {
*/ */
@JvmName("queryImageUrlAsync") @JvmName("queryImageUrlAsync")
fun __queryImageUrlAsyncForJava__(image: Image): Future<String> { fun __queryImageUrlAsyncForJava__(image: Image): Future<String> {
return future { queryImageUrl(image) } return future { image.queryUrl() }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment