From e971fd769dff5c293116a53e61fb3a60bb6357cf Mon Sep 17 00:00:00 2001 From: "jiahua.liu" Date: Sun, 16 Feb 2020 20:10:12 +0800 Subject: [PATCH] =?UTF-8?q?Mirai=20Console=20=EF=BC=88Terminal=EF=BC=89V0.?= =?UTF-8?q?01?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mirai/console/MiraiConsoleTerminalUI.kt | 58 +++++++++++++++++-- .../net/mamoe/mirai/console/MiraiConsole.kt | 14 +---- .../net/mamoe/mirai/console/MiraiConsoleUI.kt | 6 ++ .../mamoe/mirai/utils/BotConfigurationJvm.kt | 2 +- 4 files changed, 61 insertions(+), 19 deletions(-) diff --git a/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt b/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt index 15c5d5940..a6a9d8ad9 100644 --- a/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt +++ b/mirai-console-terminal/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleTerminalUI.kt @@ -12,22 +12,24 @@ import com.googlecode.lanterna.terminal.TerminalResizeListener import com.googlecode.lanterna.terminal.swing.SwingTerminal import com.googlecode.lanterna.terminal.swing.SwingTerminalFontConfiguration import com.googlecode.lanterna.terminal.swing.SwingTerminalFrame -import kotlinx.coroutines.GlobalScope -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.launch +import kotlinx.coroutines.* +import kotlinx.coroutines.io.close +import kotlinx.io.core.IoBuffer +import kotlinx.io.core.use import net.mamoe.mirai.Bot import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.cleanPage import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.drawLog import net.mamoe.mirai.console.MiraiConsoleTerminalUI.LoggerDrawer.redrawLogs +import net.mamoe.mirai.utils.LoginSolver +import net.mamoe.mirai.utils.writeChannel import java.awt.Font +import java.io.File import java.io.OutputStream import java.io.PrintStream import java.nio.charset.Charset import java.util.* import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentLinkedDeque -import java.util.concurrent.ConcurrentLinkedQueue import kotlin.concurrent.thread import kotlin.system.exitProcess @@ -97,6 +99,52 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI { botAdminCount[identity] = admins.size } + override fun createLoginSolver(): LoginSolver { + return object : LoginSolver() { + override suspend fun onSolvePicCaptcha(bot: Bot, data: IoBuffer): String? { + val tempFile: File = createTempFile(suffix = ".png").apply { deleteOnExit() } + withContext(Dispatchers.IO) { + tempFile.createNewFile() + pushLog(0, "[Login Solver]需要图片验证码登录, 验证码为 4 字母") + try { + tempFile.writeChannel().apply { writeFully(data); close() } + pushLog(0, "将会显示字符图片. 若看不清字符图片, 请查看文件 ${tempFile.absolutePath}") + } catch (e: Exception) { + error("[Login Solver]验证码无法保存[Error0001]") + } + } + pushLog(0, "[Login Solver]请输入 4 位字母验证码. 若要更换验证码, 请直接回车") + return requestInput("[Login Solver]请输入 4 位字母验证码. 若要更换验证码, 请直接回车")!!.takeUnless { it.isEmpty() || it.length != 4 } + .also { + pushLog(0, "[Login Solver]正在提交[$it]中...") + } + } + + override suspend fun onSolveSliderCaptcha(bot: Bot, url: String): String? { + pushLog(0, "[Login Solver]需要滑动验证码") + pushLog(0, "[Login Solver]请在任意浏览器中打开以下链接并完成验证码. ") + pushLog(0, "[Login Solver]完成后请输入任意字符 ") + pushLog(0, url) + return requestInput("[Login Solver]完成后请输入任意字符").also { + pushLog(0, "[Login Solver]正在提交中") + } + } + + + override suspend fun onSolveUnsafeDeviceLoginVerify(bot: Bot, url: String): String? { + pushLog(0, "[Login Solver]需要进行账户安全认证") + pushLog(0, "[Login Solver]该账户有[设备锁]/[不常用登陆地点]/[不常用设备登陆]的问题") + pushLog(0, "[Login Solver]完成以下账号认证即可成功登陆|理论本认证在mirai每个账户中最多出现1次") + pushLog(0, "[Login Solver]请将该链接在QQ浏览器中打开并完成认证, 成功后输入任意字符") + pushLog(0, "[Login Solver]这步操作将在后续的版本中优化") + pushLog(0, url) + return requestInput("[Login Solver]完成后请输入任意字符").also { + pushLog(0, "[Login Solver]正在提交中...") + } + } + + } + } val log = ConcurrentHashMap>().also { it[0L] = LimitLinkedQueue(cacheLogSize) diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index 62df4dc71..4b46a63c0 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -123,19 +123,7 @@ object MiraiConsole { runBlocking { frontEnd.prePushBot(qqNumber) val bot = Bot(qqNumber, qqPassword) { - this.loginSolver = DefaultLoginSolver(object : LoginSolverInputReader { - override suspend fun read(question: String): String? { - return frontEnd.requestInput(question) - } - }, - SimpleLogger("Login Helper") { _, message, e -> - logger("[Login Helper]", qqNumber, message) - if (e != null) { - logger("[NETWORK ERROR]", qqNumber, e.toString())//因为在一页 所以可以不打QQ - e.printStackTrace() - } - } - ) + this.loginSolver = frontEnd.createLoginSolver() this.botLoggerSupplier = { SimpleLogger("BOT $qqNumber]") { _, message, e -> logger("[BOT $qqNumber]", qqNumber, message) diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleUI.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleUI.kt index a0c7d78ca..f7784ee33 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleUI.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleUI.kt @@ -1,6 +1,7 @@ package net.mamoe.mirai.console import net.mamoe.mirai.Bot +import net.mamoe.mirai.utils.LoginSolver /** * 只需要实现一个这个 传入MiraiConsole 就可以绑定UI层与Console层 @@ -57,4 +58,9 @@ interface MiraiConsoleUI { admins: List ) + /** + * 由UI层创建一个LoginSolver + */ + fun createLoginSolver(): LoginSolver + } \ No newline at end of file diff --git a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt index 736e1f6a6..3aa3d1f56 100644 --- a/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt +++ b/mirai-core/src/jvmMain/kotlin/net/mamoe/mirai/utils/BotConfigurationJvm.kt @@ -118,7 +118,7 @@ class DefaultLoginSolver( } // Copied from Ktor CIO -private fun File.writeChannel( +public fun File.writeChannel( coroutineContext: CoroutineContext = Dispatchers.IO ): ByteWriteChannel = GlobalScope.reader(CoroutineName("file-writer") + coroutineContext, autoFlush = true) { @Suppress("BlockingMethodInNonBlockingContext")