diff --git a/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt new file mode 100644 index 000000000..4bf840092 --- /dev/null +++ b/mirai-core-qqandroid/src/androidMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -0,0 +1,13 @@ +package net.mamoe.mirai.qqandroid + +import net.mamoe.mirai.BotAccount +import net.mamoe.mirai.utils.MiraiLogger +import kotlin.coroutines.CoroutineContext + +internal actual class QQAndroidBot actual constructor( + account: BotAccount, + logger: MiraiLogger?, + context: CoroutineContext +) : QQAndroidBotBase(account, logger, context) { + +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt new file mode 100644 index 000000000..a33d63638 --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -0,0 +1,68 @@ +package net.mamoe.mirai.qqandroid + +import net.mamoe.mirai.BotAccount +import net.mamoe.mirai.BotImpl +import net.mamoe.mirai.contact.* +import net.mamoe.mirai.data.AddFriendResult +import net.mamoe.mirai.data.ImageLink +import net.mamoe.mirai.message.data.Image +import net.mamoe.mirai.qqandroid.network.QQAndroidBotNetworkHandler +import net.mamoe.mirai.utils.BotConfiguration +import net.mamoe.mirai.utils.MiraiInternalAPI +import net.mamoe.mirai.utils.MiraiLogger +import kotlin.coroutines.CoroutineContext + +internal expect class QQAndroidBot( + account: BotAccount, + logger: MiraiLogger?, + context: CoroutineContext +) : QQAndroidBotBase + +@UseExperimental(MiraiInternalAPI::class) +internal abstract class QQAndroidBotBase constructor( + account: BotAccount, + logger: MiraiLogger?, + context: CoroutineContext +) : BotImpl(account, logger, context) { + override val qqs: ContactList + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + + override fun getQQ(id: Long): QQ { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override fun createNetworkHandler(coroutineContext: CoroutineContext): QQAndroidBotNetworkHandler { + return QQAndroidBotNetworkHandler(this as QQAndroidBot) + } + + override val groups: ContactList + get() = TODO("not implemented") //To change initializer of created properties use File | Settings | File Templates. + + override suspend fun getGroup(id: GroupId): Group { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override suspend fun getGroup(internalId: GroupInternalId): Group { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override suspend fun getGroup(id: Long): Group { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override suspend fun login(configuration: BotConfiguration) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override suspend fun Image.getLink(): ImageLink { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override suspend fun approveFriendAddRequest(id: Long, remark: String?) { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } +} \ 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 new file mode 100644 index 000000000..5df914ceb --- /dev/null +++ b/mirai-core-qqandroid/src/commonMain/kotlin/net/mamoe/mirai/qqandroid/network/QQAndroidBotNetworkHandler.kt @@ -0,0 +1,22 @@ +package net.mamoe.mirai.qqandroid.network + +import kotlinx.coroutines.CompletableJob +import kotlinx.coroutines.Job +import kotlinx.coroutines.SupervisorJob +import net.mamoe.mirai.network.BotNetworkHandler +import net.mamoe.mirai.qqandroid.QQAndroidBot +import kotlin.coroutines.CoroutineContext + +internal class QQAndroidBotNetworkHandler(override val bot: QQAndroidBot) : BotNetworkHandler() { + override val supervisor: CompletableJob = SupervisorJob(bot.coroutineContext[Job]) + + override suspend fun login() { + TODO("not implemented") //To change body of created functions use File | Settings | File Templates. + } + + override suspend fun awaitDisconnection() { + TODO() + } + + override val coroutineContext: CoroutineContext = bot.coroutineContext +} \ No newline at end of file diff --git a/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt b/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt new file mode 100644 index 000000000..08d031a45 --- /dev/null +++ b/mirai-core-qqandroid/src/jvmMain/kotlin/net/mamoe/mirai/qqandroid/QQAndroidBot.kt @@ -0,0 +1,18 @@ +package net.mamoe.mirai.qqandroid + +import kotlinx.coroutines.GlobalScope +import net.mamoe.mirai.BotAccount +import net.mamoe.mirai.alsoLogin +import net.mamoe.mirai.utils.MiraiLogger +import kotlin.coroutines.CoroutineContext + +internal actual class QQAndroidBot actual constructor( + account: BotAccount, + logger: MiraiLogger?, + context: CoroutineContext +) : QQAndroidBotBase(account, logger, context) + +suspend fun main() { + val bot = QQAndroidBot(BotAccount(1, ""), null, GlobalScope.coroutineContext).alsoLogin() + bot.network.awaitDisconnection() +} \ No newline at end of file diff --git a/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/TIMPCBot.kt b/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/TIMPCBot.kt index 7348f0c4a..4128a110e 100644 --- a/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/TIMPCBot.kt +++ b/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/TIMPCBot.kt @@ -19,7 +19,7 @@ import net.mamoe.mirai.timpc.internal.RawGroupInfo import net.mamoe.mirai.timpc.network.GroupImpl import net.mamoe.mirai.timpc.network.MemberImpl import net.mamoe.mirai.timpc.network.QQImpl -import net.mamoe.mirai.timpc.network.TIMBotNetworkHandler +import net.mamoe.mirai.timpc.network.TIMPCBotNetworkHandler import net.mamoe.mirai.timpc.network.handler.TemporaryPacketHandler import net.mamoe.mirai.timpc.network.packet.action.* import net.mamoe.mirai.timpc.network.packet.event.EventPacketFactory @@ -46,7 +46,7 @@ internal abstract class TIMPCBotBase constructor( account: BotAccount, logger: MiraiLogger?, context: CoroutineContext -) : BotImpl(account, logger ?: DefaultLogger("Bot(" + account.id + ")"), context) { +) : BotImpl(account, logger ?: DefaultLogger("Bot(" + account.id + ")"), context) { @UseExperimental(ExperimentalUnsignedTypes::class) companion object { @@ -85,47 +85,10 @@ internal abstract class TIMPCBotBase constructor( } } - final override val network: TIMBotNetworkHandler get() = _network + inline val sessionKey: SessionKey get()= network.sessionKey - inline val sessionKey: SessionKey get() = network.sessionKey - - private lateinit var _network: TIMBotNetworkHandler - - override suspend fun login(configuration: BotConfiguration) = - reinitializeNetworkHandler(configuration, null) - - // shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close - internal fun tryReinitializeNetworkHandler( - configuration: BotConfiguration, - cause: Throwable? - ): Job = launch { - repeat(configuration.reconnectionRetryTimes) { - try { - reinitializeNetworkHandler(configuration, cause) - logger.info("Reconnected successfully") - return@launch - } catch (e: LoginFailedException) { - delay(configuration.reconnectPeriodMillis) - } - } - } - - private suspend fun reinitializeNetworkHandler( - configuration: BotConfiguration, - cause: Throwable? - ) { - logger.info("BotAccount: $qqAccount") - logger.info("Initializing BotNetworkHandler") - try { - if (::_network.isInitialized) { - _network.close(cause) - } - } catch (e: Exception) { - logger.error("Cannot close network handler", e) - } - _network = TIMBotNetworkHandler(this.coroutineContext + configuration, this as TIMPCBot) - - _network.login() + override fun createNetworkHandler(coroutineContext: CoroutineContext): TIMPCBotNetworkHandler { + return TIMPCBotNetworkHandler(coroutineContext, this as TIMPCBot) } final override suspend fun addFriend(id: Long, message: String?, remark: String?): AddFriendResult { diff --git a/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMBotNetworkHandler.kt b/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMPCBotNetworkHandler.kt similarity index 98% rename from mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMBotNetworkHandler.kt rename to mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMPCBotNetworkHandler.kt index de4f5860d..ccd019d0e 100644 --- a/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMBotNetworkHandler.kt +++ b/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/TIMPCBotNetworkHandler.kt @@ -37,7 +37,7 @@ internal expect val NetworkDispatcher: CoroutineDispatcher * * @see BotNetworkHandler */ -internal class TIMBotNetworkHandler internal constructor(coroutineContext: CoroutineContext, bot: TIMPCBot) : +internal class TIMPCBotNetworkHandler internal constructor(coroutineContext: CoroutineContext, bot: TIMPCBot) : BotNetworkHandler(), CoroutineScope { override val bot: TIMPCBot by bot.unsafeWeakRef() override val supervisor: CompletableJob = SupervisorJob(coroutineContext[Job]) @@ -160,7 +160,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou with(id.factory) { loginHandler!!.provideDecrypter(id.factory) .decrypt(input) - .decode(id, sequenceId, this@TIMBotNetworkHandler) + .decode(id, sequenceId, this@TIMPCBotNetworkHandler) } } finally { input.close() @@ -272,7 +272,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou Unit } - override val owner: Bot get() = this@TIMBotNetworkHandler.bot + override val owner: Bot get() = this@TIMPCBotNetworkHandler.bot override fun close() { loginHandler?.close() @@ -452,7 +452,7 @@ internal class TIMBotNetworkHandler internal constructor(coroutineContext: Corou BotLoginSucceedEvent(bot).broadcast() val configuration = currentBotConfiguration() - heartbeatJob = this@TIMBotNetworkHandler.launch { + heartbeatJob = this@TIMPCBotNetworkHandler.launch { while (socket.isOpen) { delay(configuration.heartbeatPeriodMillis) with(bot) { diff --git a/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/packet/event/EventPacketFactory.kt b/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/packet/event/EventPacketFactory.kt index a5abf9556..5f958ee87 100644 --- a/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/packet/event/EventPacketFactory.kt +++ b/mirai-core-timpc/src/commonMain/kotlin/net.mamoe.mirai.timpc/network/packet/event/EventPacketFactory.kt @@ -7,7 +7,7 @@ import net.mamoe.mirai.Bot import net.mamoe.mirai.network.BotNetworkHandler import net.mamoe.mirai.data.Packet import net.mamoe.mirai.network.packet.* -import net.mamoe.mirai.timpc.network.TIMBotNetworkHandler +import net.mamoe.mirai.timpc.network.TIMPCBotNetworkHandler import net.mamoe.mirai.qqAccount import net.mamoe.mirai.timpc.network.packet.buildSessionPacket import net.mamoe.mirai.utils.io.readIoBuffer @@ -46,7 +46,7 @@ internal object EventPacketFactory : PacketFactory(SessionKe to = readUInt().toLong(), // clear semantic uniqueId = readIoBuffer(8) ) - (handler as TIMBotNetworkHandler).socket.sendPacket(EventPacketFactory(id, sequenceId, handler.bot.qqAccount, handler.sessionKey, eventIdentity)) + (handler as TIMPCBotNetworkHandler).socket.sendPacket(EventPacketFactory(id, sequenceId, handler.bot.qqAccount, handler.sessionKey, eventIdentity)) discardExact(2) // 1F 40 return with(matchEventPacketFactory(readUShort())) { parse(handler.bot, eventIdentity) }.also { diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt index 356d01473..06abb60a9 100644 --- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt +++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/BotImpl.kt @@ -2,15 +2,9 @@ package net.mamoe.mirai -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.* import net.mamoe.mirai.network.BotNetworkHandler -import net.mamoe.mirai.utils.DefaultLogger -import net.mamoe.mirai.utils.LockFreeLinkedList -import net.mamoe.mirai.utils.MiraiInternalAPI -import net.mamoe.mirai.utils.MiraiLogger +import net.mamoe.mirai.utils.* import net.mamoe.mirai.utils.io.logStacktrace import kotlin.coroutines.CoroutineContext @@ -56,7 +50,49 @@ abstract class BotImpl constructor( // region network - abstract override val network: N + final override val network: N get() = _network + + private lateinit var _network: N + + override suspend fun login(configuration: BotConfiguration) = + reinitializeNetworkHandler(configuration, null) + + // shouldn't be suspend!! This function MUST NOT inherit the context from the caller because the caller(NetworkHandler) is going to close + fun tryReinitializeNetworkHandler( + configuration: BotConfiguration, + cause: Throwable? + ): Job = launch { + repeat(configuration.reconnectionRetryTimes) { + try { + reinitializeNetworkHandler(configuration, cause) + logger.info("Reconnected successfully") + return@launch + } catch (e: LoginFailedException) { + delay(configuration.reconnectPeriodMillis) + } + } + } + + private suspend fun reinitializeNetworkHandler( + configuration: BotConfiguration, + cause: Throwable? + ) { + logger.info("BotAccount: $qqAccount") + logger.info("Initializing BotNetworkHandler") + try { + if (::_network.isInitialized) { + _network.close(cause) + } + } catch (e: Exception) { + logger.error("Cannot close network handler", e) + } + _network = createNetworkHandler(this.coroutineContext + configuration) + + _network.login() + } + + protected abstract fun createNetworkHandler(coroutineContext: CoroutineContext): N + // endregion @UseExperimental(MiraiInternalAPI::class)