Commit 624d4714 authored by Him188's avatar Him188

Small updates

parent ba7e50de
...@@ -29,6 +29,8 @@ kotlin { ...@@ -29,6 +29,8 @@ kotlin {
} }
} }
jvmTest {
}
all { all {
languageSettings.enableLanguageFeature("InlineClasses") languageSettings.enableLanguageFeature("InlineClasses")
...@@ -36,7 +38,7 @@ kotlin { ...@@ -36,7 +38,7 @@ kotlin {
} }
} }
compileKotlinJvm{ compileKotlinJvm {
} }
......
...@@ -27,7 +27,7 @@ val Bot.qqs: ContactList<QQ> get() = this.contacts.qqs ...@@ -27,7 +27,7 @@ val Bot.qqs: ContactList<QQ> get() = this.contacts.qqs
//NetworkHandler //NetworkHandler
suspend fun Bot.sendPacket(packet: ClientPacket) = this.network.socket.sendPacket(packet) 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 //BotAccount
......
...@@ -54,10 +54,8 @@ interface BotNetworkHandler { ...@@ -54,10 +54,8 @@ interface BotNetworkHandler {
/** /**
* 尝试登录 * 尝试登录
*
* @param touchingTimeoutMillis 连接每个服务器的 timeout
*/ */
suspend fun login(touchingTimeoutMillis: Long = 200): LoginState suspend fun login(): LoginState
/** /**
* 添加一个临时包处理器 * 添加一个临时包处理器
......
package net.mamoe.mirai.network.protocol.tim package net.mamoe.mirai.network.protocol.tim
import kotlinx.coroutines.* import kotlinx.coroutines.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.broadcast import net.mamoe.mirai.event.broadcast
import net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent import net.mamoe.mirai.event.events.bot.BotLoginSucceedEvent
...@@ -48,20 +50,20 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler { ...@@ -48,20 +50,20 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
temporaryPacketHandlers.add(temporaryPacketHandler) temporaryPacketHandlers.add(temporaryPacketHandler)
} }
override suspend fun login(touchingTimeoutMillis: Long): LoginState { override suspend fun login(): LoginState {
return loginInternal(touchingTimeoutMillis, LinkedList(TIMProtocol.SERVER_IP)) 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() this.socket.close()
val ip = ipQueue.poll() ?: return LoginState.UNKNOWN//所有服务器均返回 UNKNOWN val ip = ipQueue.poll() ?: return LoginState.UNKNOWN//所有服务器均返回 UNKNOWN
return this.socket.touch(ip, touchingTimeoutMillis).await().let { state -> return socket.touch(ip).let { state ->
if (state == LoginState.UNKNOWN || state == LoginState.TIMEOUT) { //if (state == LoginState.UNKNOWN || state == LoginState.TIMEOUT) {
loginInternal(touchingTimeoutMillis, ipQueue)//超时或未知, 重试连接下一个服务器 // loginInternal(ipQueue)//超时或未知, 重试连接下一个服务器
} else { //} else {
state state
} // }
} }
} }
...@@ -121,14 +123,14 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler { ...@@ -121,14 +123,14 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
return return
} }
withContext(NetworkScope.coroutineContext) { withContext(NetworkScope.coroutineContext + CoroutineExceptionHandler { _, e -> e.printStackTrace() }) {
launch { launch(this.coroutineContext) {
loginHandler.onPacketReceived(packet) loginHandler.onPacketReceived(packet)
} }
packetHandlers.forEach { packetHandlers.forEach {
launch { launch(this.coroutineContext) {
it.instance.onPacketReceived(packet) it.instance.onPacketReceived(packet)
} }
} }
...@@ -151,10 +153,10 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler { ...@@ -151,10 +153,10 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
socket?.close() socket?.close()
socket = DatagramSocket(0) socket = DatagramSocket(0)
socket!!.connect(InetSocketAddress(serverIP, 8000)) socket!!.connect(InetSocketAddress(serverIP, 8000))
GlobalScope.launch { NetworkScope.launch {
while (socket?.isConnected == true) { while (socket?.isConnected == true) {
val packet = DatagramPacket(ByteArray(2048), 2048) val packet = DatagramPacket(ByteArray(2048), 2048)
kotlin.runCatching { socket?.receive(packet) } kotlin.runCatching { withContext(Dispatchers.IO) { socket?.receive(packet) } }
.onSuccess { .onSuccess {
NetworkScope.launch { NetworkScope.launch {
distributePacket(ServerPacket.ofByteArray(packet.data.removeZeroTail())) distributePacket(ServerPacket.ofByteArray(packet.data.removeZeroTail()))
...@@ -174,8 +176,9 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler { ...@@ -174,8 +176,9 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
/** /**
* Start network and touch the server * 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") bot.info("Connecting server: $serverAddress")
restartSocket()
if (this@TIMBotNetworkHandler::loginHandler.isInitialized) { if (this@TIMBotNetworkHandler::loginHandler.isInitialized) {
loginHandler.close() loginHandler.close()
} }
...@@ -183,19 +186,16 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler { ...@@ -183,19 +186,16 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
this.loginResult = CompletableDeferred() this.loginResult = CompletableDeferred()
serverIP = serverAddress serverIP = serverAddress
bot.waitForPacket(ServerPacket::class, timeoutMillis) { //bot.waitForPacket(ServerTouchResponsePacket::class, timeoutMillis) {
loginResult!!.complete(LoginState.TIMEOUT) // loginResult?.complete(LoginState.TIMEOUT)
} //}
runBlocking { sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP))
sendPacket(ClientTouchPacket(bot.account.qqNumber, serverIP))
}
return this.loginResult!! return withContext(Dispatchers.IO) {
loginResult!!.await()
}
} }
/**
* Not async
*/
@Synchronized @Synchronized
override suspend fun sendPacket(packet: ClientPacket) { override suspend fun sendPacket(packet: ClientPacket) {
checkNotNull(socket) { "network closed" } checkNotNull(socket) { "network closed" }
...@@ -240,6 +240,10 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler { ...@@ -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 { ...@@ -312,21 +316,24 @@ internal class TIMBotNetworkHandler(private val bot: Bot) : BotNetworkHandler {
if (packet.transmissionCompleted) { if (packet.transmissionCompleted) {
//todo 验证码多样化处理 //todo 验证码多样化处理
withContext(Dispatchers.IO) {
bot.notice(CharImageUtil.createCharImg(ImageIO.read(captchaCache!!.inputStream()))) val code = captchaLock.withLock {
} withContext(Dispatchers.IO) {
bot.notice("需要验证码登录, 验证码为 4 字母") bot.notice(ImageIO.read(captchaCache!!.inputStream()).createCharImg())
try { }
File(System.getProperty("user.dir") + "/temp/Captcha.png") bot.notice("需要验证码登录, 验证码为 4 字母")
.also { withContext(Dispatchers.IO) { it.createNewFile() } } try {
.writeBytes(this.captchaCache!!) File(System.getProperty("user.dir") + "/temp/Captcha.png")
bot.notice("若看不清字符图片, 请查看 Mirai 目录下 /temp/Captcha.png") .also { withContext(Dispatchers.IO) { it.createNewFile() } }
} catch (e: Exception) { .writeBytes(this.captchaCache!!)
bot.notice("无法写出验证码文件, 请尝试查看以上字符图片") bot.notice("若看不清字符图片, 请查看 Mirai 目录下 /temp/Captcha.png")
} catch (e: Exception) {
bot.notice("无法写出验证码文件, 请尝试查看以上字符图片")
}
this.captchaCache = null
bot.notice("若要更换验证码, 请直接回车")
Scanner(System.`in`).nextLine()
} }
this.captchaCache = null
bot.notice("若要更换验证码, 请直接回车")
val code = Scanner(System.`in`).nextLine()
if (code.isEmpty() || code.length != 4) { if (code.isEmpty() || code.length != 4) {
this.captchaCache = byteArrayOf() this.captchaCache = byteArrayOf()
this.captchaSectionId = 1 this.captchaSectionId = 1
......
...@@ -2,8 +2,10 @@ ...@@ -2,8 +2,10 @@
package net.mamoe.mirai.network.protocol.tim.packet package net.mamoe.mirai.network.protocol.tim.packet
import kotlinx.coroutines.*
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent import net.mamoe.mirai.event.events.network.ServerPacketReceivedEvent
import net.mamoe.mirai.event.subscribeAlways
import net.mamoe.mirai.event.subscribeWhileTrue import net.mamoe.mirai.event.subscribeWhileTrue
import net.mamoe.mirai.network.protocol.tim.packet.PacketNameFormatter.adjustName import net.mamoe.mirai.network.protocol.tim.packet.PacketNameFormatter.adjustName
import net.mamoe.mirai.network.protocol.tim.packet.action.ServerCanAddFriendResponsePacket import net.mamoe.mirai.network.protocol.tim.packet.action.ServerCanAddFriendResponsePacket
...@@ -337,42 +339,19 @@ fun DataInputStream.gotoWhere(matcher: ByteArray): DataInputStream { ...@@ -337,42 +339,19 @@ fun DataInputStream.gotoWhere(matcher: ByteArray): DataInputStream {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
internal fun <P : ServerPacket> Bot.waitForPacket(packetClass: KClass<P>, timeoutMillis: Long = Long.MAX_VALUE, timeout: () -> Unit = {}) { internal fun <P : ServerPacket> Bot.waitForPacket(packetClass: KClass<P>, timeoutMillis: Long = Long.MAX_VALUE, timeout: () -> Unit = {}) {
var got = false var got = false
ServerPacketReceivedEvent::class.subscribeWhileTrue { ServerPacketReceivedEvent.subscribeWhileTrue {
if (packetClass.isInstance(it.packet) && it.bot === this) { if (packetClass.isInstance(it.packet) && it.bot === this) {
got = true got = true
true
} else {
false false
} else {
true
} }
} }
GlobalScope.launch(Dispatchers.Unconfined) {
MiraiThreadPool.instance.submit { delay(timeoutMillis)
val startingTime = System.currentTimeMillis() if (!got) {
while (!got) { timeout.invoke()
if (System.currentTimeMillis() - startingTime > timeoutMillis) {
timeout.invoke()
return@submit
}
Thread.sleep(10)
} }
} }
} }
\ No newline at end of file
/*
@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
...@@ -4,6 +4,7 @@ import net.mamoe.mirai.network.protocol.tim.TIMProtocol ...@@ -4,6 +4,7 @@ import net.mamoe.mirai.network.protocol.tim.TIMProtocol
import net.mamoe.mirai.network.protocol.tim.packet.* import net.mamoe.mirai.network.protocol.tim.packet.*
import net.mamoe.mirai.utils.TEA import net.mamoe.mirai.utils.TEA
import net.mamoe.mirai.utils.Tested import net.mamoe.mirai.utils.Tested
import net.mamoe.mirai.utils.cutTail
import net.mamoe.mirai.utils.hexToBytes import net.mamoe.mirai.utils.hexToBytes
import java.io.DataInputStream import java.io.DataInputStream
......
...@@ -5,11 +5,7 @@ import java.awt.image.BufferedImage ...@@ -5,11 +5,7 @@ import java.awt.image.BufferedImage
/** /**
* @author NaturalHG * @author NaturalHG
*/ */
object CharImageUtil { @JvmOverloads
fun BufferedImage.createCharImg(sizeWeight: Int = 100, sizeHeight: Int = 20): String {
@JvmOverloads return CharImageConverter(this, sizeWeight).call()
fun createCharImg(image: BufferedImage, sizeWeight: Int = 100, sizeHeight: Int = 20): String {
return CharImageConverter(image, sizeWeight).call()
}
} }
\ No newline at end of file
...@@ -33,7 +33,7 @@ interface MiraiLogger { ...@@ -33,7 +33,7 @@ interface MiraiLogger {
/** /**
* 由 mirai-console 或 mirai-web 等模块实现 * 由 mirai-console 或 mirai-web 等模块实现
*/ */
lateinit var defaultLogger: () -> MiraiLogger var defaultLogger: () -> MiraiLogger = { Console() }
val DEBUGGING: Boolean by lazy { val DEBUGGING: Boolean by lazy {
//avoid inspections //avoid inspections
......
...@@ -167,4 +167,9 @@ object GZip { ...@@ -167,4 +167,9 @@ object GZip {
GZIPOutputStream(it).write(bytes) GZIPOutputStream(it).write(bytes)
return it.toByteArray() 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
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.coroutines.withTimeout
import net.mamoe.mirai.Bot 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.network.protocol.tim.packet.login.LoginState
import net.mamoe.mirai.utils.BotAccount import net.mamoe.mirai.utils.BotAccount
import net.mamoe.mirai.utils.Console import net.mamoe.mirai.utils.Console
...@@ -14,68 +16,33 @@ import java.util.* ...@@ -14,68 +16,33 @@ import java.util.*
* @author Him188moe * @author Him188moe
*/ */
val qqList = "2535777366----abc123456\n" + const val qqList = "" +
"2535815148----abc123456\n" + "3383596103----13978930542\n" +
"2535704896----abc123456\n" + "3342679146----aaaa9899\n" +
"2535744882----abc123456\n" + "1491095272----abc123\n" +
"2535656918----abc123456\n" + "3361065539----aaaa9899\n" +
"2535679286----abc123456\n" + "1077612696----asd123456789\n" +
"2535606374----abc123456\n" + "\n" +
"2535647743----abc123456\n" + "\n" +
"2535543049----abc123456\n" + "\n" +
"2535583893----abc123456\n" + "\n" +
"2535508338----abc123456\n" + "\n" +
"2535524178----abc123456\n" + "\n" +
"2535363077----abc123456\n" + "\n" +
"2535469090----abc123456\n" + "\n" +
"2535263758----abc123456\n" + "\n" +
"2535258328----abc123456\n" + "\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() { suspend fun main() {
val goodBotList = Collections.synchronizedList(mutableListOf<Bot>()) val goodBotList = Collections.synchronizedList(mutableListOf<Bot>())
withContext(Dispatchers.Default) { withContext(NetworkScope.coroutineContext) {
qqList.split("\n") qqList.split("\n")
.filterNot { it.isEmpty() } .filterNot { it.isEmpty() }
.map { it.split("----") } .map { it.split("----") }
.map { Pair(it[0].toLong(), it[1]) } .map { Pair(it[0].toLong(), it[1]) }
.forEach { (qq, password) -> .forEach { (qq, password) ->
launch { runBlocking {
val bot = Bot( val bot = Bot(
BotAccount( BotAccount(
qq, qq,
...@@ -85,19 +52,16 @@ suspend fun main() { ...@@ -85,19 +52,16 @@ suspend fun main() {
) )
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
withTimeout(3000) { bot.login()
bot.network.tryLogin().await()
}
}.let { state -> }.let { state ->
if (!(state == LoginState.BLOCKED || state == LoginState.DEVICE_LOCK || state == LoginState.WRONG_PASSWORD)) { if (state == LoginState.SUCCESS) {
goodBotList.add(bot) goodBotList.add(bot)
} else {
} }
} }
} }
} }
} }
println("Filtering finished")
println(goodBotList.joinToString("\n") { it.account.qqNumber.toString() + " " + it.account.password }) println(goodBotList.joinToString("\n") { it.account.qqNumber.toString() + " " + it.account.password })
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment