mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-05 00:10:13 +08:00
Move BotImpl
and BotNetworkHandler
to mirai-core-qqandroid.
This commit is contained in:
parent
84c47c9fe5
commit
ae32536ed5
@ -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))
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
}
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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,
|
||||
/**
|
||||
|
@ -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")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,11 +1,14 @@
|
||||
package net.mamoe.mirai.qqandroid.network
|
||||
|
||||
import net.mamoe.mirai.utils.MiraiInternalAPI
|
||||
|
||||
/**
|
||||
* 从服务器收到的包解析之后的结构化数据.
|
||||
* 它是一个数据包工厂的处理的返回值.
|
||||
*
|
||||
* **InternalAPI**: 这是内部 API, 它随时都有可能被修改
|
||||
*/
|
||||
@MiraiInternalAPI
|
||||
interface Packet {
|
||||
/**
|
||||
* 实现这个接口的包将不会被记录到日志中
|
||||
|
@ -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 }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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() }
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user