From 624d4714321217fb08a3e1647ef6de0bc62c2e59 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Thu, 3 Oct 2019 21:12:54 +0800
Subject: [PATCH] Small updates

---
 mirai-core/build.gradle                       |   4 +-
 .../kotlin/net/mamoe/mirai/BotHelper.kt       |   2 +-
 .../mamoe/mirai/network/BotNetworkHandler.kt  |   4 +-
 .../protocol/tim/TIMBotNetworkHandler.kt      |  83 +++++++-------
 .../protocol/tim/packet/ServerPacket.kt       |  41 ++-----
 .../tim/packet/login/VerificationCode.kt      |   1 +
 .../net/mamoe/mirai/utils/CharImageUtil.kt    |  10 +-
 .../net/mamoe/mirai/utils/MiraiLogger.kt      |   2 +-
 .../kotlin/net/mamoe/mirai/utils/Utils.kt     |   7 +-
 mirai-core/src/jvmTest/kotlin/BadQQFilter.kt  |  67 ++++++++++++
 .../kotlin}/ImageOutputTest.java              |   0
 .../java => jvmTest/kotlin}/NetworkTest.java  |   0
 .../{test/java => jvmTest/kotlin}/data.txxt   |   0
 .../kotlin}/event/EventTest.kt                |   0
 mirai-core/src/test/java/BadQQFilter.kt       | 103 ------------------
 15 files changed, 138 insertions(+), 186 deletions(-)
 create mode 100644 mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
 rename mirai-core/src/{test/java => jvmTest/kotlin}/ImageOutputTest.java (100%)
 rename mirai-core/src/{test/java => jvmTest/kotlin}/NetworkTest.java (100%)
 rename mirai-core/src/{test/java => jvmTest/kotlin}/data.txxt (100%)
 rename mirai-core/src/{test/java => jvmTest/kotlin}/event/EventTest.kt (100%)
 delete mode 100644 mirai-core/src/test/java/BadQQFilter.kt

diff --git a/mirai-core/build.gradle b/mirai-core/build.gradle
index 6403a2f58..0d14eb059 100644
--- a/mirai-core/build.gradle
+++ b/mirai-core/build.gradle
@@ -29,6 +29,8 @@ kotlin {
 
             }
         }
+        jvmTest {
+        }
 
         all {
             languageSettings.enableLanguageFeature("InlineClasses")
@@ -36,7 +38,7 @@ kotlin {
     }
 }
 
-compileKotlinJvm{
+compileKotlinJvm {
 
 }
 
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotHelper.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotHelper.kt
index 1ba27a7bb..200dbd05e 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotHelper.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/BotHelper.kt
@@ -27,7 +27,7 @@ val Bot.qqs: ContactList<QQ> get() = this.contacts.qqs
 //NetworkHandler
 suspend fun Bot.sendPacket(packet: ClientPacket) = this.network.socket.sendPacket(packet)
 
-suspend fun Bot.login(touchingTimeoutMillis: Long = 200): LoginState = this.network.login()
+suspend fun Bot.login(): LoginState = this.network.login()
 
 //BotAccount
 
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/BotNetworkHandler.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/BotNetworkHandler.kt
index 9ee2f67f2..d04982eb9 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/BotNetworkHandler.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/BotNetworkHandler.kt
@@ -54,10 +54,8 @@ interface BotNetworkHandler {
 
     /**
      * 尝试登录
-     *
-     * @param touchingTimeoutMillis 连接每个服务器的 timeout
      */
-    suspend fun login(touchingTimeoutMillis: Long = 200): LoginState
+    suspend fun login(): LoginState
 
     /**
      * 添加一个临时包处理器
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/TIMBotNetworkHandler.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/TIMBotNetworkHandler.kt
index c6aab67e0..37b30e6a4 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/TIMBotNetworkHandler.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/TIMBotNetworkHandler.kt
@@ -1,6 +1,8 @@
 package net.mamoe.mirai.network.protocol.tim
 
 import kotlinx.coroutines.*
+import kotlinx.coroutines.sync.Mutex
+import kotlinx.coroutines.sync.withLock
 import net.mamoe.mirai.Bot
 import net.mamoe.mirai.event.broadcast
 import net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent
@@ -48,20 +50,20 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
         temporaryPacketHandlers.add(temporaryPacketHandler)
     }
 
-    override suspend fun login(touchingTimeoutMillis: Long): LoginState {
-        return loginInternal(touchingTimeoutMillis, LinkedList(TIMProtocol.SERVER_IP))
+    override suspend fun login(): LoginState {
+        return loginInternal(LinkedList(TIMProtocol.SERVER_IP))
     }
 
-    private suspend fun loginInternal(touchingTimeoutMillis: Long, ipQueue: LinkedList<String>): LoginState {
+    private suspend fun loginInternal(ipQueue: LinkedList<String>): LoginState {
         this.socket.close()
         val ip = ipQueue.poll() ?: return LoginState.UNKNOWN//所有服务器均返回 UNKNOWN
 
-        return this.socket.touch(ip, touchingTimeoutMillis).await().let { state ->
-            if (state == LoginState.UNKNOWN || state == LoginState.TIMEOUT) {
-                loginInternal(touchingTimeoutMillis, ipQueue)//超时或未知, 重试连接下一个服务器
-            } else {
+        return socket.touch(ip).let { state ->
+            //if (state == LoginState.UNKNOWN || state == LoginState.TIMEOUT) {
+            //    loginInternal(ipQueue)//超时或未知, 重试连接下一个服务器
+            //} else {
                 state
-            }
+            // }
         }
     }
 
@@ -121,14 +123,14 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
                 return
             }
 
-            withContext(NetworkScope.coroutineContext) {
-                launch {
+            withContext(NetworkScope.coroutineContext + CoroutineExceptionHandler { _, e -> e.printStackTrace() }) {
+                launch(this.coroutineContext) {
                     loginHandler.onPacketReceived(packet)
                 }
 
 
                 packetHandlers.forEach {
-                    launch {
+                    launch(this.coroutineContext) {
                         it.instance.onPacketReceived(packet)
                     }
                 }
@@ -151,10 +153,10 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
             socket?.close()
             socket = DatagramSocket(0)
             socket!!.connect(InetSocketAddress(serverIP, 8000))
-            GlobalScope.launch {
+            NetworkScope.launch {
                 while (socket?.isConnected == true) {
                     val packet = DatagramPacket(ByteArray(2048), 2048)
-                    kotlin.runCatching { socket?.receive(packet) }
+                    kotlin.runCatching { withContext(Dispatchers.IO) { socket?.receive(packet) } }
                             .onSuccess {
                                 NetworkScope.launch {
                                     distributePacket(ServerPacket.ofByteArray(packet.data.removeZeroTail()))
@@ -174,8 +176,9 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
         /**
          * Start network and touch the server
          */
-        fun touch(serverAddress: String, timeoutMillis: Long): CompletableDeferred<LoginState> {
+        internal suspend fun touch(serverAddress: String): LoginState {
             bot.info("Connecting server: $serverAddress")
+            restartSocket()
             if (this@TIMBotNetworkHandler::loginHandler.isInitialized) {
                 loginHandler.close()
             }
@@ -183,19 +186,16 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
             this.loginResult = CompletableDeferred()
 
             serverIP = serverAddress
-            bot.waitForPacket(ServerPacket::class, timeoutMillis) {
-                loginResult!!.complete(LoginState.TIMEOUT)
-            }
-            runBlocking {
-                sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP))
-            }
+            //bot.waitForPacket(ServerTouchResponsePacket::class, timeoutMillis) {
+            //    loginResult?.complete(LoginState.TIMEOUT)
+            //}
+            sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP))
 
-            return this.loginResult!!
+            return withContext(Dispatchers.IO) {
+                loginResult!!.await()
+            }
         }
 
-        /**
-         * Not async
-         */
         @Synchronized
         override suspend fun sendPacket(packet: ClientPacket) {
             checkNotNull(socket) { "network closed" }
@@ -240,6 +240,10 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
         }
     }
 
+    companion object {
+        val captchaLock = Mutex()
+    }
+
     /**
      * 处理登录过程
      */
@@ -312,21 +316,24 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
 
                     if (packet.transmissionCompleted) {
                         //todo 验证码多样化处理
-                        withContext(Dispatchers.IO) {
-                            bot.notice(CharImageUtil.createCharImg(ImageIO.read(captchaCache!!.inputStream())))
+
+                        val code = captchaLock.withLock {
+                            withContext(Dispatchers.IO) {
+                                bot.notice(ImageIO.read(captchaCache!!.inputStream()).createCharImg())
+                            }
+                            bot.notice("需要验证码登录, 验证码为 4 字母")
+                            try {
+                                File(System.getProperty("user.dir") + "/temp/Captcha.png")
+                                        .also { withContext(Dispatchers.IO) { it.createNewFile() } }
+                                        .writeBytes(this.captchaCache!!)
+                                bot.notice("若看不清字符图片, 请查看 Mirai 目录下 /temp/Captcha.png")
+                            } catch (e: Exception) {
+                                bot.notice("无法写出验证码文件, 请尝试查看以上字符图片")
+                            }
+                            this.captchaCache = null
+                            bot.notice("若要更换验证码, 请直接回车")
+                            Scanner(System.`in`).nextLine()
                         }
-                        bot.notice("需要验证码登录, 验证码为 4 字母")
-                        try {
-                            File(System.getProperty("user.dir") + "/temp/Captcha.png")
-                                    .also { withContext(Dispatchers.IO) { it.createNewFile() } }
-                                    .writeBytes(this.captchaCache!!)
-                            bot.notice("若看不清字符图片, 请查看 Mirai 目录下 /temp/Captcha.png")
-                        } catch (e: Exception) {
-                            bot.notice("无法写出验证码文件, 请尝试查看以上字符图片")
-                        }
-                        this.captchaCache = null
-                        bot.notice("若要更换验证码, 请直接回车")
-                        val code = Scanner(System.`in`).nextLine()
                         if (code.isEmpty() || code.length != 4) {
                             this.captchaCache = byteArrayOf()
                             this.captchaSectionId = 1
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/ServerPacket.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/ServerPacket.kt
index e1b9cfb4c..3b50dbeea 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/ServerPacket.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/ServerPacket.kt
@@ -2,8 +2,10 @@
 
 package net.mamoe.mirai.network.protocol.tim.packet
 
+import kotlinx.coroutines.*
 import net.mamoe.mirai.Bot
 import net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
+import net.mamoe.mirai.event.subscribeAlways
 import net.mamoe.mirai.event.subscribeWhileTrue
 import net.mamoe.mirai.network.protocol.tim.packet.PacketNameFormatter.adjustName
 import net.mamoe.mirai.network.protocol.tim.packet.action.ServerCanAddFriendResponsePacket
@@ -337,42 +339,19 @@ fun DataInputStream.gotoWhere(matcher: ByteArray): DataInputStream {
 @Suppress("UNCHECKED_CAST")
 internal fun <P : ServerPacket> Bot.waitForPacket(packetClass: KClass<P>, timeoutMillis: Long = Long.MAX_VALUE, timeout: () -> Unit = {}) {
     var got = false
-    ServerPacketReceivedEvent::class.subscribeWhileTrue {
+    ServerPacketReceivedEvent.subscribeWhileTrue {
         if (packetClass.isInstance(it.packet) && it.bot === this) {
             got = true
-            true
-        } else {
             false
+        } else {
+            true
         }
     }
 
-
-    MiraiThreadPool.instance.submit {
-        val startingTime = System.currentTimeMillis()
-        while (!got) {
-            if (System.currentTimeMillis() - startingTime > timeoutMillis) {
-                timeout.invoke()
-                return@submit
-            }
-            Thread.sleep(10)
+    GlobalScope.launch(Dispatchers.Unconfined) {
+        delay(timeoutMillis)
+        if (!got) {
+            timeout.invoke()
         }
     }
-}
-
-/*
-@Throws(EOFException::class)
-fun DataInputStream.gotoWhere(matcher: ByteArray) {
-    require(matcher.isNotEmpty())
-    do {
-        val byte = this.readByte()
-        if (byte == matcher[0]) {
-            for (i in 1 until matcher.size){
-
-            }
-        }
-    } while (true)
-}*/
-
-fun ByteArray.cutTail(length: Int): ByteArray = this.copyOfRange(0, this.size - length)
-
-fun ByteArray.getRight(length: Int): ByteArray = this.copyOfRange(this.size - length, this.size)
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/login/VerificationCode.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/login/VerificationCode.kt
index 996b16389..21e6315a6 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/login/VerificationCode.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/network/protocol/tim/packet/login/VerificationCode.kt
@@ -4,6 +4,7 @@ import net.mamoe.mirai.network.protocol.tim.TIMProtocol
 import net.mamoe.mirai.network.protocol.tim.packet.*
 import net.mamoe.mirai.utils.TEA
 import net.mamoe.mirai.utils.Tested
+import net.mamoe.mirai.utils.cutTail
 import net.mamoe.mirai.utils.hexToBytes
 import java.io.DataInputStream
 
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/CharImageUtil.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/CharImageUtil.kt
index 88effe66f..cc1dee354 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/CharImageUtil.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/CharImageUtil.kt
@@ -5,11 +5,7 @@ import java.awt.image.BufferedImage
 /**
  * @author NaturalHG
  */
-object CharImageUtil {
-
-    @JvmOverloads
-    fun createCharImg(image: BufferedImage, sizeWeight: Int = 100, sizeHeight: Int = 20): String {
-        return CharImageConverter(image, sizeWeight).call()
-    }
-
+@JvmOverloads
+fun BufferedImage.createCharImg(sizeWeight: Int = 100, sizeHeight: Int = 20): String {
+    return CharImageConverter(this, sizeWeight).call()
 }
\ No newline at end of file
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLogger.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLogger.kt
index 9490e05f0..eb61743a2 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLogger.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/MiraiLogger.kt
@@ -33,7 +33,7 @@ interface MiraiLogger {
 /**
  * 由 mirai-console 或 mirai-web 等模块实现
  */
-lateinit var defaultLogger: () -> MiraiLogger
+var defaultLogger: () -> MiraiLogger = { Console() }
 
 val DEBUGGING: Boolean by lazy {
     //avoid inspections
diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Utils.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Utils.kt
index c6d4e5e57..f7a8d691a 100644
--- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Utils.kt
+++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/Utils.kt
@@ -167,4 +167,9 @@ object GZip {
         GZIPOutputStream(it).write(bytes)
         return it.toByteArray()
     }
-}
\ No newline at end of file
+}
+
+
+fun ByteArray.cutTail(length: Int): ByteArray = this.copyOfRange(0, this.size - length)
+
+fun ByteArray.getRight(length: Int): ByteArray = this.copyOfRange(this.size - length, this.size)
\ No newline at end of file
diff --git a/mirai-core/src/jvmTest/kotlin/BadQQFilter.kt b/mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
new file mode 100644
index 000000000..7ca90250f
--- /dev/null
+++ b/mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
@@ -0,0 +1,67 @@
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.runBlocking
+import kotlinx.coroutines.withContext
+import net.mamoe.mirai.Bot
+import net.mamoe.mirai.login
+import net.mamoe.mirai.network.NetworkScope
+import net.mamoe.mirai.network.protocol.tim.packet.login.LoginState
+import net.mamoe.mirai.utils.BotAccount
+import net.mamoe.mirai.utils.Console
+import java.util.*
+
+/**
+ * 筛选掉无法登录(冻结/设备锁/UNKNOWN)的 qq
+ *
+ * @author Him188moe
+ */
+
+const val qqList = "" +
+        "3383596103----13978930542\n" +
+        "3342679146----aaaa9899\n" +
+        "1491095272----abc123\n" +
+        "3361065539----aaaa9899\n" +
+        "1077612696----asd123456789\n" +
+        "\n" +
+        "\n" +
+        "\n" +
+        "\n" +
+        "\n" +
+        "\n" +
+        "\n" +
+        "\n" +
+        "\n" +
+        "\n"
+
+suspend fun main() {
+    val goodBotList = Collections.synchronizedList(mutableListOf<Bot>())
+
+    withContext(NetworkScope.coroutineContext) {
+        qqList.split("\n")
+                .filterNot { it.isEmpty() }
+                .map { it.split("----") }
+                .map { Pair(it[0].toLong(), it[1]) }
+                .forEach { (qq, password) ->
+                    runBlocking {
+                        val bot = Bot(
+                                BotAccount(
+                                        qq,
+                                        if (password.endsWith(".")) password.substring(0, password.length - 1) else password
+                                ),
+                                Console()
+                        )
+
+                        withContext(Dispatchers.IO) {
+                            bot.login()
+                        }.let { state ->
+                            if (state == LoginState.SUCCESS) {
+                                goodBotList.add(bot)
+                            }
+                        }
+                    }
+                }
+    }
+
+    println("Filtering finished")
+    println(goodBotList.joinToString("\n") { it.account.qqNumber.toString() + "    " + it.account.password })
+}
diff --git a/mirai-core/src/test/java/ImageOutputTest.java b/mirai-core/src/jvmTest/kotlin/ImageOutputTest.java
similarity index 100%
rename from mirai-core/src/test/java/ImageOutputTest.java
rename to mirai-core/src/jvmTest/kotlin/ImageOutputTest.java
diff --git a/mirai-core/src/test/java/NetworkTest.java b/mirai-core/src/jvmTest/kotlin/NetworkTest.java
similarity index 100%
rename from mirai-core/src/test/java/NetworkTest.java
rename to mirai-core/src/jvmTest/kotlin/NetworkTest.java
diff --git a/mirai-core/src/test/java/data.txxt b/mirai-core/src/jvmTest/kotlin/data.txxt
similarity index 100%
rename from mirai-core/src/test/java/data.txxt
rename to mirai-core/src/jvmTest/kotlin/data.txxt
diff --git a/mirai-core/src/test/java/event/EventTest.kt b/mirai-core/src/jvmTest/kotlin/event/EventTest.kt
similarity index 100%
rename from mirai-core/src/test/java/event/EventTest.kt
rename to mirai-core/src/jvmTest/kotlin/event/EventTest.kt
diff --git a/mirai-core/src/test/java/BadQQFilter.kt b/mirai-core/src/test/java/BadQQFilter.kt
deleted file mode 100644
index 196badace..000000000
--- a/mirai-core/src/test/java/BadQQFilter.kt
+++ /dev/null
@@ -1,103 +0,0 @@
-import kotlinx.coroutines.Dispatchers
-import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
-import kotlinx.coroutines.withTimeout
-import net.mamoe.mirai.Bot
-import net.mamoe.mirai.network.protocol.tim.packet.login.LoginState
-import net.mamoe.mirai.utils.BotAccount
-import net.mamoe.mirai.utils.Console
-import java.util.*
-
-/**
- * 筛选掉无法登录(冻结/设备锁/UNKNOWN)的 qq
- *
- * @author Him188moe
- */
-
-val qqList = "2535777366----abc123456\n" +
-        "2535815148----abc123456\n" +
-        "2535704896----abc123456\n" +
-        "2535744882----abc123456\n" +
-        "2535656918----abc123456\n" +
-        "2535679286----abc123456\n" +
-        "2535606374----abc123456\n" +
-        "2535647743----abc123456\n" +
-        "2535543049----abc123456\n" +
-        "2535583893----abc123456\n" +
-        "2535508338----abc123456\n" +
-        "2535524178----abc123456\n" +
-        "2535363077----abc123456\n" +
-        "2535469090----abc123456\n" +
-        "2535263758----abc123456\n" +
-        "2535258328----abc123456\n" +
-        "2535175332----abc123456\n" +
-        "2535175855----abc123456\n" +
-        "2535126490----abc123456\n" +
-        "2535169081----abc123456\n" +
-        "2535054551----abc123456\n" +
-        "2535085068----abc123456\n" +
-        "2535041182----abc123456\n" +
-        "2535055583----abc123456\n" +
-        "2534883752----abc123456\n" +
-        "2534909231----abc123456\n" +
-        "2534715278----abc123456\n" +
-        "2534766467----abc123456\n" +
-        "2534696956----abc123456\n" +
-        "2534703892----abc123456\n" +
-        "2534597961----abc123456\n" +
-        "2534687923----abc123456\n" +
-        "2534573690----abc123456\n" +
-        "2534596747----abc123456\n" +
-        "2534467863----abc123456\n" +
-        "2534480141----abc123456\n" +
-        "2534377951----abc123456\n" +
-        "2534418547----abc123456\n" +
-        "2534315990----abc123456\n" +
-        "2534318348----abc123456\n" +
-        "2534220616----abc123456\n" +
-        "2534288430----abc123456\n" +
-        "2534205633----abc123456\n" +
-        "2534226589----abc123456\n" +
-        "2534182470----abc123456\n" +
-        "2534194558----abc123456\n" +
-        "2534106061----abc123456\n" +
-        "2534108283----abc123456\n" +
-        "2534026460----abc123456\n" +
-        "2534037598----abc123456\n"
-
-
-suspend fun main() {
-    val goodBotList = Collections.synchronizedList(mutableListOf<Bot>())
-
-    withContext(Dispatchers.Default) {
-        qqList.split("\n")
-                .filterNot { it.isEmpty() }
-                .map { it.split("----") }
-                .map { Pair(it[0].toLong(), it[1]) }
-                .forEach { (qq, password) ->
-                    launch {
-                        val bot = Bot(
-                                BotAccount(
-                                        qq,
-                                        if (password.endsWith(".")) password.substring(0, password.length - 1) else password
-                                ),
-                                Console()
-                        )
-
-                        withContext(Dispatchers.IO) {
-                            withTimeout(3000) {
-                                bot.network.tryLogin().await()
-                            }
-                        }.let { state ->
-                            if (!(state == LoginState.BLOCKED || state == LoginState.DEVICE_LOCK || state == LoginState.WRONG_PASSWORD)) {
-                                goodBotList.add(bot)
-                            } else {
-
-                            }
-                        }
-                    }
-                }
-    }
-
-    println(goodBotList.joinToString("\n") { it.account.qqNumber.toString() + "    " + it.account.password })
-}