mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-23 22:00:10 +08:00
Rearrange QQAndroidBot
This commit is contained in:
parent
1d053bd1bd
commit
997ad1eb63
@ -20,13 +20,15 @@ package net.mamoe.mirai.internal
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.contact.ContactList
|
||||
import net.mamoe.mirai.contact.OtherClient
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.event.*
|
||||
import net.mamoe.mirai.event.EventPriority.MONITOR
|
||||
import net.mamoe.mirai.event.events.BotEvent
|
||||
import net.mamoe.mirai.event.events.BotOfflineEvent
|
||||
import net.mamoe.mirai.internal.network.DefaultServerList
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.uin
|
||||
import net.mamoe.mirai.internal.network.handler.NetworkHandler
|
||||
import net.mamoe.mirai.internal.network.handler.ServerList
|
||||
import net.mamoe.mirai.supervisorJob
|
||||
@ -71,11 +73,17 @@ internal abstract class AbstractBot constructor(
|
||||
// overrides
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
final override val isOnline: Boolean get() = _network.state == NetworkHandler.State.OK
|
||||
final override val isOnline: Boolean get() = network.state == NetworkHandler.State.OK
|
||||
final override val eventChannel: EventChannel<BotEvent> =
|
||||
GlobalEventChannel.filterIsInstance<BotEvent>().filter { it.bot === this@AbstractBot }
|
||||
|
||||
override val otherClients: ContactList<OtherClient> = ContactList()
|
||||
final override val otherClients: ContactList<OtherClient> = ContactList()
|
||||
final override val friends: ContactList<Friend> = ContactList()
|
||||
final override val groups: ContactList<Group> = ContactList()
|
||||
final override val strangers: ContactList<Stranger> = ContactList()
|
||||
|
||||
final override val asFriend: Friend by lazy { Mirai.newFriend(this, FriendInfoImpl(uin, nick, "")) }
|
||||
final override val asStranger: Stranger by lazy { Mirai.newStranger(bot, StrangerInfoImpl(bot.id, bot.nick)) }
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// sync (// TODO: 2021/4/14 extract sync logic
|
||||
@ -96,7 +104,6 @@ internal abstract class AbstractBot constructor(
|
||||
val bot = bot.asQQAndroidBot()
|
||||
if (
|
||||
!event.bot.isActive // bot closed
|
||||
|| !::_network.isInitialized // bot 还未登录就被 close
|
||||
// || _isConnecting // bot 还在登入 // TODO: 2021/4/14 处理还在登入?
|
||||
) {
|
||||
// Close network to avoid endless reconnection while network is ok
|
||||
@ -137,7 +144,7 @@ internal abstract class AbstractBot constructor(
|
||||
}
|
||||
|
||||
if (event.reconnect) {
|
||||
if (_network.state != NetworkHandler.State.OK) {
|
||||
if (network.state != NetworkHandler.State.OK) {
|
||||
// normally closed
|
||||
return@subscribeAlways
|
||||
}
|
||||
@ -145,15 +152,6 @@ internal abstract class AbstractBot constructor(
|
||||
val causeMessage = event.castOrNull<BotOfflineEvent.CauseAware>()?.cause?.toString() ?: event.toString()
|
||||
bot.logger.info { "Connection lost, retrying login ($causeMessage)" }
|
||||
|
||||
bot.asQQAndroidBot().client.run {
|
||||
if (serverList.isEmpty()) {
|
||||
bot.bdhSyncer.loadServerListFromCache()
|
||||
if (serverList.isEmpty()) {
|
||||
serverList.addAll(DefaultServerList)
|
||||
} else Unit
|
||||
} else serverList.removeAt(0)
|
||||
}
|
||||
|
||||
bot.launch {
|
||||
val success: Boolean
|
||||
val time = measureTime {
|
||||
@ -173,13 +171,13 @@ internal abstract class AbstractBot constructor(
|
||||
|
||||
internal val serverList: MutableList<Pair<String, Int>> = mutableListOf() // TODO: 2021/4/16 remove old
|
||||
internal val serverListNew = ServerList() // TODO: 2021/4/16 load server list from cache (add a provider)
|
||||
// bot.bdhSyncer.loadServerListFromCache()
|
||||
|
||||
// TODO: 2021/4/14 handle serverList
|
||||
|
||||
val network: NetworkHandler get() = _network
|
||||
|
||||
@Suppress("PropertyName")
|
||||
internal lateinit var _network: NetworkHandler
|
||||
val network: NetworkHandler by lazy {
|
||||
createNetworkHandler(coroutineContext)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
@ -188,10 +186,11 @@ internal abstract class AbstractBot constructor(
|
||||
*/
|
||||
final override suspend fun login() {
|
||||
if (!isActive) error("Bot is already closed and cannot relogin. Please create a new Bot instance then do login.")
|
||||
network
|
||||
network.resumeConnection()
|
||||
}
|
||||
|
||||
protected abstract fun createNetworkHandler(coroutineContext: CoroutineContext): NetworkHandler
|
||||
protected abstract suspend fun sendLogout()
|
||||
|
||||
// endregion
|
||||
|
||||
@ -211,11 +210,10 @@ internal abstract class AbstractBot constructor(
|
||||
}
|
||||
groups.delegate.clear() // job is cancelled, so child jobs are to be cancelled
|
||||
friends.delegate.clear()
|
||||
strangers.delegate.clear()
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract suspend fun sendLogout()
|
||||
|
||||
override fun close(cause: Throwable?) {
|
||||
if (!this.isActive) {
|
||||
// already cancelled
|
||||
|
@ -12,13 +12,11 @@ package net.mamoe.mirai.internal
|
||||
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.LowLevelApi
|
||||
import net.mamoe.mirai.Mirai
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.OtherClientInfo
|
||||
import net.mamoe.mirai.internal.contact.OtherClientImpl
|
||||
import net.mamoe.mirai.internal.contact.checkIsGroupImpl
|
||||
import net.mamoe.mirai.internal.contact.info.FriendInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.info.StrangerInfoImpl
|
||||
import net.mamoe.mirai.internal.contact.uin
|
||||
import net.mamoe.mirai.internal.network.*
|
||||
import net.mamoe.mirai.internal.network.handler.*
|
||||
@ -56,58 +54,72 @@ internal class QQAndroidBot constructor(
|
||||
internal val account: BotAccount,
|
||||
configuration: BotConfiguration
|
||||
) : AbstractBot(configuration, account.id), SsoContext {
|
||||
val bdhSyncer: BdhSessionSyncer = BdhSessionSyncer(this)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Account secrets cache
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// We cannot extract these logics until we rewrite the network framework.
|
||||
|
||||
private val cacheDir: File by lazy {
|
||||
configuration.workingDir.resolve(bot.configuration.cacheDir).apply { mkdirs() }
|
||||
}
|
||||
internal val accountSecretsFile: File by lazy {
|
||||
cacheDir.resolve("account.secrets")
|
||||
}
|
||||
|
||||
private fun saveSecrets(secrets: AccountSecretsImpl) {
|
||||
if (secrets.wLoginSigInfoField == null) return
|
||||
|
||||
accountSecretsFile.writeBytes(
|
||||
TEA.encrypt(
|
||||
secrets.toByteArray(AccountSecretsImpl.serializer()),
|
||||
account.passwordMd5
|
||||
)
|
||||
)
|
||||
|
||||
network.context.logger.info { "Saved account secrets to local cache for fast login." }
|
||||
}
|
||||
|
||||
init {
|
||||
if (configuration.loginCacheEnabled) {
|
||||
eventChannel.parentScope(this).subscribeAlways<WtLogin.Login.LoginPacketResponse> { event ->
|
||||
if (event is WtLogin.Login.LoginPacketResponse.Success) {
|
||||
if (client.wLoginSigInfoInitialized) {
|
||||
saveSecrets(AccountSecretsImpl(client))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////// accounts secrets end
|
||||
|
||||
override lateinit var client: QQAndroidClient
|
||||
|
||||
|
||||
override val bot: QQAndroidBot get() = this
|
||||
|
||||
val bdhSyncer: BdhSessionSyncer = BdhSessionSyncer(this)
|
||||
internal var firstLoginSucceed: Boolean = false
|
||||
|
||||
inline val json get() = configuration.json
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// network
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override val friends: ContactList<Friend> = ContactList()
|
||||
// TODO: 2021/4/14 bdhSyncer.loadFromCache() when login
|
||||
|
||||
override suspend fun sendLogout() {
|
||||
network.sendWithoutExpect(StatSvc.Register.offline(client))
|
||||
}
|
||||
|
||||
override fun createNetworkHandler(coroutineContext: CoroutineContext): NetworkHandler {
|
||||
val context = NetworkHandlerContextImpl(this, this)
|
||||
return SelectorNetworkHandler(
|
||||
context,
|
||||
FactoryKeepAliveNetworkHandlerSelector(NettyNetworkHandlerFactory, serverListNew, context)
|
||||
) // We can move the factory to configuration but this is not necessary for now.
|
||||
}
|
||||
|
||||
|
||||
suspend inline fun <E : Packet> OutgoingPacketWithRespType<E>.sendAndExpect(
|
||||
timeoutMillis: Long = 5000,
|
||||
retry: Int = 2
|
||||
): E = network.run { sendAndExpect(timeoutMillis, retry) }
|
||||
|
||||
suspend inline fun <E : Packet> OutgoingPacket.sendAndExpect(timeoutMillis: Long = 5000, retry: Int = 2): E =
|
||||
network.run { sendAndExpect(timeoutMillis, retry) }
|
||||
|
||||
/**
|
||||
* 获取 获取群公告 所需的 bkn 参数
|
||||
* */
|
||||
val bkn: Int
|
||||
get() = client.wLoginSigInfo.sKey.data
|
||||
.fold(5381) { acc: Int, b: Byte -> acc + acc.shl(5) + b.toInt() }
|
||||
.and(Int.MAX_VALUE)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// contacts
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override lateinit var nick: String
|
||||
|
||||
@JvmField
|
||||
val groupListModifyLock = Mutex()
|
||||
|
||||
// internally visible only
|
||||
fun getGroupByUin(uin: Long): Group {
|
||||
return getGroupByUinOrNull(uin)
|
||||
?: throw NoSuchElementException("Group ${Mirai.calculateGroupCodeByGroupUin(uin)} not found")
|
||||
}
|
||||
|
||||
fun getGroupByUinOrNull(uin: Long): Group? {
|
||||
return groups.firstOrNull { it.checkIsGroupImpl(); it.uin == uin }
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// contact cache
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
inline val json get() = configuration.json
|
||||
|
||||
val friendListCache: FriendListCache? by lazy {
|
||||
if (!configuration.contactListCache.friendListCacheEnabled) return@lazy null
|
||||
@ -146,58 +158,44 @@ internal class QQAndroidBot constructor(
|
||||
}
|
||||
}
|
||||
|
||||
override lateinit var nick: String
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Account secrets cache
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
override val asFriend: Friend by lazy {
|
||||
@OptIn(LowLevelApi::class)
|
||||
Mirai.newFriend(this, FriendInfoImpl(uin, nick, ""))
|
||||
// We cannot extract these logics until we rewrite the network framework.
|
||||
|
||||
private val cacheDir: File by lazy {
|
||||
configuration.workingDir.resolve(bot.configuration.cacheDir).apply { mkdirs() }
|
||||
}
|
||||
private val accountSecretsFile: File by lazy {
|
||||
cacheDir.resolve("account.secrets")
|
||||
}
|
||||
|
||||
override val groups: ContactList<Group> = ContactList()
|
||||
private fun saveSecrets(secrets: AccountSecretsImpl) {
|
||||
if (secrets.wLoginSigInfoField == null) return
|
||||
|
||||
// TODO: 2021/4/14 bdhSyncer.loadFromCache() when login
|
||||
accountSecretsFile.writeBytes(
|
||||
TEA.encrypt(
|
||||
secrets.toByteArray(AccountSecretsImpl.serializer()),
|
||||
account.passwordMd5
|
||||
)
|
||||
)
|
||||
|
||||
override suspend fun sendLogout() {
|
||||
network.sendWithoutExpect(StatSvc.Register.offline(client))
|
||||
network.context.logger.info { "Saved account secrets to local cache for fast login." }
|
||||
}
|
||||
|
||||
override fun createNetworkHandler(coroutineContext: CoroutineContext): NetworkHandler {
|
||||
val context = NetworkHandlerContextImpl(this, this)
|
||||
return SelectorNetworkHandler(
|
||||
context,
|
||||
FactoryKeepAliveNetworkHandlerSelector(NettyNetworkHandlerFactory, serverListNew, context)
|
||||
) // We can move the factory to configuration but this is not necessary for now.
|
||||
init {
|
||||
if (configuration.loginCacheEnabled) {
|
||||
eventChannel.parentScope(this).subscribeAlways<WtLogin.Login.LoginPacketResponse> { event ->
|
||||
if (event is WtLogin.Login.LoginPacketResponse.Success) {
|
||||
if (client.wLoginSigInfoInitialized) {
|
||||
saveSecrets(AccountSecretsImpl(client))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmField
|
||||
val groupListModifyLock = Mutex()
|
||||
/////////////////////////// accounts secrets end
|
||||
|
||||
// internally visible only
|
||||
fun getGroupByUin(uin: Long): Group {
|
||||
return getGroupByUinOrNull(uin)
|
||||
?: throw NoSuchElementException("Group ${Mirai.calculateGroupCodeByGroupUin(uin)} not found")
|
||||
}
|
||||
|
||||
fun getGroupByUinOrNull(uin: Long): Group? {
|
||||
return groups.firstOrNull { it.checkIsGroupImpl(); it.uin == uin }
|
||||
}
|
||||
|
||||
|
||||
suspend inline fun <E : Packet> OutgoingPacketWithRespType<E>.sendAndExpect(
|
||||
timeoutMillis: Long = 5000,
|
||||
retry: Int = 2
|
||||
): E = network.run { sendAndExpect(timeoutMillis, retry) }
|
||||
|
||||
suspend inline fun <E : Packet> OutgoingPacket.sendAndExpect(timeoutMillis: Long = 5000, retry: Int = 2): E =
|
||||
network.run { sendAndExpect(timeoutMillis, retry) }
|
||||
|
||||
/**
|
||||
* 获取 获取群公告 所需的 bkn 参数
|
||||
* */
|
||||
val bkn: Int
|
||||
get() = client.wLoginSigInfo.sKey.data
|
||||
.fold(5381) { acc: Int, b: Byte -> acc + acc.shl(5) + b.toInt() }
|
||||
.and(Int.MAX_VALUE)
|
||||
override val asStranger: Stranger by lazy { Mirai.newStranger(bot, StrangerInfoImpl(bot.id, bot.nick)) }
|
||||
override val strangers: ContactList<Stranger> = ContactList()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user