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 }) -}