Commit d0fb1383 authored by jiahua.liu's avatar jiahua.liu

Mirai Console V0.01

parent 90157c8f
......@@ -7,9 +7,11 @@ class MiraiConsoleTerminalLoader {
@JvmStatic
fun main(args: Array<String>) {
MiraiConsoleTerminalUI.start()
MiraiConsole.start(
MiraiConsoleTerminalUI
)
thread {
MiraiConsole.start(
MiraiConsoleTerminalUI
)
}
Runtime.getRuntime().addShutdownHook(thread(start = false) {
MiraiConsole.stop()
})
......
......@@ -25,6 +25,8 @@ 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
......@@ -44,7 +46,7 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
val cacheLogSize = 50
override fun pushLog(identity: Long, message: String) {
log[identity]!!.offer(message)
log[identity]!!.push(message)
if (identity == screens[currentScreenId]) {
drawLog(message)
}
......@@ -52,23 +54,49 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
override fun prePushBot(identity: Long) {
log[identity] = LimitLinkedQueue(cacheLogSize)
botAdminCount[identity] = 0
screens.add(identity)
}
override fun pushBot(bot: Bot) {
//nothing to do
botAdminCount[bot.uin] = 0
screens.add(bot.uin)
drawFrame(this.getScreenName(currentScreenId))
if (terminal is SwingTerminalFrame) {
terminal.flush()
}
}
var requesting = false
var requestResult: String? = null
override suspend fun requestInput(question: String): String {
requesting = true
while (requesting) {
Thread.sleep(100)//不然会卡死 迷惑吧
}
return requestResult!!
}
fun provideInput(input: String) {
if (requesting) {
requestResult = input
requesting = false
} else {
MiraiConsole.CommandListener.commandChannel.offer(
commandBuilder.toString()
)
}
}
override fun pushBotAdminStatus(identity: Long, admins: List<Long>) {
botAdminCount[identity] = admins.size
}
val log = mutableMapOf<Long, Queue<String>>().also {
val log = ConcurrentHashMap<Long, LimitLinkedQueue<String>>().also {
it[0L] = LimitLinkedQueue(cacheLogSize)
}
val botAdminCount = mutableMapOf<Long, Int>()
val botAdminCount = ConcurrentHashMap<Long, Int>()
private val screens = mutableListOf(0L)
private var currentScreenId = 0
......@@ -202,9 +230,7 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
update()
}
KeyType.Enter -> {
MiraiConsole.CommandListener.commandChannel.offer(
commandBuilder.toString()
)
provideInput(commandBuilder.toString())
emptyCommand()
}
KeyType.Escape -> {
......@@ -333,6 +359,9 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
fun drawLog(string: String, flush: Boolean = true) {
val maxHeight = terminal.terminalSize.rows - 4
val heightNeed = (string.length / (terminal.terminalSize.columns - 6)) + 1
if (heightNeed - 1 > maxHeight) {
return//拒绝打印
}
if (currentHeight + heightNeed > maxHeight) {
cleanPage()
}
......@@ -421,7 +450,7 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
private fun addCommandChar(
c: Char
) {
if (commandBuilder.isEmpty() && c != '/') {
if (!requesting && commandBuilder.isEmpty() && c != '/') {
addCommandChar('/')
}
textGraphics.foregroundColor = TextColor.ANSI.WHITE
......@@ -488,11 +517,11 @@ object MiraiConsoleTerminalUI : MiraiConsoleUI {
class LimitLinkedQueue<T>(
val limit: Int = 50
) : ConcurrentLinkedQueue<T>() {
override fun offer(e: T): Boolean {
) : ConcurrentLinkedDeque<T>() {
override fun push(e: T) {
if (size >= limit) {
poll()
this.pollLast()
}
return super.offer(e)
return super.push(e)
}
}
......@@ -11,7 +11,6 @@ package net.mamoe.mirai.console
import kotlinx.coroutines.runBlocking
import net.mamoe.mirai.Bot
import net.mamoe.mirai.alsoLogin
import net.mamoe.mirai.api.http.MiraiHttpAPIServer
import net.mamoe.mirai.api.http.generateSessionKey
import net.mamoe.mirai.console.plugins.PluginManager
......@@ -19,7 +18,7 @@ import net.mamoe.mirai.console.plugins.loadAsConfig
import net.mamoe.mirai.console.plugins.withDefaultWrite
import net.mamoe.mirai.console.plugins.withDefaultWriteSave
import net.mamoe.mirai.contact.sendMessage
import net.mamoe.mirai.utils.SimpleLogger
import net.mamoe.mirai.utils.*
import java.io.File
import java.util.*
import java.util.concurrent.LinkedBlockingQueue
......@@ -119,12 +118,39 @@ object MiraiConsole {
logger("[Bot Login]", 0, "login...")
try {
runBlocking {
Bot(qqNumber, qqPassword).alsoLogin()
frontEnd.prePushBot(qqNumber)
val bot = Bot(qqNumber, qqPassword) {
this.loginSolver = DefaultLoginSolver(object : LoginSolverInputReader {
override suspend fun read(question: String): String? {
return frontEnd.requestInput(question)
}
})
this.botLoggerSupplier = {
SimpleLogger("BOT $qqNumber") { _, message, e ->
logger("[BOT $qqNumber]", qqNumber, message)
if (e != null) {
logger("[NETWORK ERROR]", qqNumber, e.toString())//因为在一页 所以可以不打QQ
e.printStackTrace()
}
}
}
this.networkLoggerSupplier = {
SimpleLogger("BOT $qqNumber") { _, message, e ->
logger("[NETWORK]", qqNumber, message)//因为在一页 所以可以不打QQ
if (e != null) {
logger("[NETWORK ERROR]", qqNumber, e.toString())//因为在一页 所以可以不打QQ
e.printStackTrace()
}
}
}
}
bot.login()
logger(
"[Bot Login]",
0,
"$qqNumber login successes"
)
frontEnd.pushBot(bot)
}
} catch (e: Exception) {
logger(
......@@ -132,7 +158,6 @@ object MiraiConsole {
0,
"$qqNumber login failed -> " + e.message
)
e.printStackTrace()
}
true
}
......
......@@ -10,7 +10,7 @@ import net.mamoe.mirai.Bot
interface MiraiConsoleUI {
/**
* 让UI层展示一条log
* identityString: log前面的prefix
*
* identity:log所属的screen, Main=0; Bot=Bot.uin
*/
fun pushLog(
......@@ -32,6 +32,15 @@ interface MiraiConsoleUI {
bot: Bot
)
/**
* 让UI层提供一个Input
* 这个Input 不 等于 Command
*
*/
suspend fun requestInput(
question: String
): String
/**
* 让UI层更新BOT管理员的数据
*/
......@@ -39,4 +48,5 @@ interface MiraiConsoleUI {
identity: Long,
admins: List<Long>
)
}
\ No newline at end of file
......@@ -39,7 +39,22 @@ import kotlin.coroutines.EmptyCoroutineContext
actual var defaultLoginSolver: LoginSolver = DefaultLoginSolver()
internal class DefaultLoginSolver : LoginSolver() {
interface LoginSolverInputReader{
suspend fun read(question:String):String?
suspend operator fun invoke(question: String):String?{
return read(question)
}
}
class DefaultLoginSolverInputReader: LoginSolverInputReader{
override suspend fun read(question: String): String? {
return readLine()
}
}
class DefaultLoginSolver(
val reader: LoginSolverInputReader = DefaultLoginSolverInputReader()
) : LoginSolver() {
override suspend fun onSolvePicCaptcha(bot: Bot, data: IoBuffer): String? = loginSolverLock.withLock {
val tempFile: File = createTempFile(suffix = ".png").apply { deleteOnExit() }
withContext(Dispatchers.IO) {
......@@ -62,7 +77,7 @@ internal class DefaultLoginSolver : LoginSolver() {
}
}
bot.logger.info("请输入 4 位字母验证码. 若要更换验证码, 请直接回车")
return readLine()!!.takeUnless { it.isEmpty() || it.length != 4 }.also {
return reader("请输入 4 位字母验证码. 若要更换验证码, 请直接回车")!!.takeUnless { it.isEmpty() || it.length != 4 }.also {
bot.logger.info("正在提交[$it]中...")
}
}
......@@ -72,7 +87,7 @@ internal class DefaultLoginSolver : LoginSolver() {
bot.logger.info("请在任意浏览器中打开以下链接并完成验证码. ")
bot.logger.info("完成后请输入任意字符 ")
bot.logger.info(url)
return readLine().also {
return reader("完成后请输入任意字符").also {
bot.logger.info("正在提交中...")
}
}
......@@ -84,7 +99,7 @@ internal class DefaultLoginSolver : LoginSolver() {
bot.logger.info("请将该链接在QQ浏览器中打开并完成认证, 成功后输入任意字符")
bot.logger.info("这步操作将在后续的版本中优化")
bot.logger.info(url)
return readLine().also {
return reader("完成后请输入任意字符").also {
bot.logger.info("正在提交中...")
}
}
......
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