mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-05 07:30:09 +08:00
Mirai Console V0.01
This commit is contained in:
parent
90157c8f80
commit
d0fb1383a0
@ -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>
|
||||
)
|
||||
|
||||
}
|
@ -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("正在提交中...")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user