mirror of
https://github.com/mamoe/mirai.git
synced 2025-03-26 07:20:09 +08:00
Small updates
This commit is contained in:
parent
ba7e50de31
commit
624d471432
mirai-core
build.gradle
src
jvmMain/kotlin/net/mamoe/mirai
jvmTest/kotlin
test/java
@ -29,6 +29,8 @@ kotlin {
|
||||
|
||||
}
|
||||
}
|
||||
jvmTest {
|
||||
}
|
||||
|
||||
all {
|
||||
languageSettings.enableLanguageFeature("InlineClasses")
|
||||
@ -36,7 +38,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
|
||||
compileKotlinJvm{
|
||||
compileKotlinJvm {
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -54,10 +54,8 @@ interface BotNetworkHandler {
|
||||
|
||||
/**
|
||||
* 尝试登录
|
||||
*
|
||||
* @param touchingTimeoutMillis 连接每个服务器的 timeout
|
||||
*/
|
||||
suspend fun login(touchingTimeoutMillis: Long = 200): LoginState
|
||||
suspend fun login(): LoginState
|
||||
|
||||
/**
|
||||
* 添加一个临时包处理器
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
@ -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
|
||||
|
||||
|
@ -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()
|
||||
}
|
@ -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
|
||||
|
@ -167,4 +167,9 @@ object GZip {
|
||||
GZIPOutputStream(it).write(bytes)
|
||||
return it.toByteArray()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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)
|
67
mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
Normal file
67
mirai-core/src/jvmTest/kotlin/BadQQFilter.kt
Normal file
@ -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 })
|
||||
}
|
@ -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 })
|
||||
}
|
Loading…
Reference in New Issue
Block a user