console wrapper

This commit is contained in:
jiahua.liu 2020-03-06 13:48:16 +08:00
parent 9c69fb1342
commit 964db6be50
8 changed files with 361 additions and 109 deletions

View File

@ -0,0 +1,117 @@
package net.mamoe.mirai.console.wrapper
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.http.URLProtocol
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.copyTo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.math.pow
import kotlin.system.exitProcess
const val CONSOLE_PURE = "Pure"
object ConsoleUpdator{
@Suppress("SpellCheckingInspection")
private object Links:HashMap<String,Map<String,String>>() {
init {
put(CONSOLE_PURE, mapOf(
"version" to "/net/mamoe/mirai-console/",
"jcenter" to "https://jcenter.bintray.com/net/mamoe/mirai-console/{version}/:mirai-console-{version}.jar",
"aliyun" to "https://maven.aliyun.com/nexus/content/repositories/jcenter/net/mamoe/mirai-console/{version}/mirai-console-{version}.jar"
))
}
}
var consoleType = CONSOLE_PURE
fun getFile():File?{
contentPath.listFiles()?.forEach { file ->
if (file != null && file.extension == "jar") {
if(file.name.contains("mirai-console")) {
when (consoleType) {
CONSOLE_PURE -> {
return file
}
}
}
}
}
return null
}
suspend fun versionCheck(type:String) {
this.consoleType = type
println("Fetching Newest Console Version of $type")
val newest = getNewestVersion()
val current = getCurrentVersion()
println("Local Console-$type Version: $current | Newest Console-$type Version: $newest")
if (current != newest) {
println("Updating Console-$type from V$current -> V$newest, this is a force update")
this.getFile()?.delete()
downloadConsole(newest)
println("Download Console complete")
}
}
private suspend fun getNewestVersion():String{
try {
return """>([0-9])*\.([0-9])*\.([0-9])*/""".toRegex().findAll(
Http.get<String> {
url {
protocol = URLProtocol.HTTPS
host = "jcenter.bintray.com"
path(Links[consoleType]!!["version"] ?: error("Unknown Console Type"))
}
}
).asSequence()
.map { it.value.drop(1).dropLast(1) }
.maxBy {
it.split('.').foldRightIndexed(0) { index: Int, s: String, acc: Int ->
acc + 100.0.pow(index).toInt() + (s.toIntOrNull() ?: 0)
}
}!!
} catch (e: Exception) {
println("Failed to fetch newest Console version, please seek for help")
e.printStackTrace()
println("Failed to fetch newest Console version, please seek for help")
exitProcess(1)
}
}
private fun getCurrentVersion():String{
val file = getFile()
if(file != null) {
val numberVersion = """([0-9])*\.([0-9])*\.([0-9])*""".toRegex().find(file.name)?.value
if (numberVersion != null) {
return numberVersion + file.name.substringAfter(numberVersion).substringBefore(".jar")
}
}
return "0.0.0"
}
private suspend fun downloadConsole(version:String){
tryNTimesOrQuit(3) {
kotlin.runCatching {
println("Downloading newest Console from Aliyun")
Http.downloadRequest(Links[consoleType]!!["aliyun"] ?: error("Unknown Console Type"), version)
}.getOrElse {
println("Downloading newest Console from JCenter")
Http.downloadRequest(Links[consoleType]!!["jcenter"] ?: error("Unknown Console Type"), version)
}
.saveTo(if (consoleType == CONSOLE_PURE) {
"mirai-console-$version.jar"
} else {
"mirai-console-$consoleType-$version.jar"
})
}
}
}

View File

@ -9,38 +9,23 @@
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.console.core
package net.mamoe.mirai.console.wrapper
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.http.URLProtocol
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.copyTo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import net.mamoe.mirai.console.MiraiConsole
import kotlinx.coroutines.*
import java.io.File
import java.net.URLClassLoader
import kotlin.math.pow
import kotlin.system.exitProcess
val Http: HttpClient
get() = HttpClient(CIO)
object CoreUpdator {
object MiraiCoreLoader {
private val coresPath by lazy {
File(System.getProperty("user.dir") + "/core/").also {
if (!it.exists()) {
it.mkdirs()
}
}
}
private fun getProtocolLib(): File? {
this.coresPath.listFiles()?.forEach { file ->
fun getProtocolLib(): File? {
contentPath.listFiles()?.forEach { file ->
if (file != null && file.extension == "jar" && file.name.contains("qqandroid")) {
return file
}
@ -48,8 +33,8 @@ object MiraiCoreLoader {
return null
}
private fun getCore(): File? {
this.coresPath.listFiles()?.forEach { file ->
fun getCore(): File? {
contentPath.listFiles()?.forEach { file ->
if (file != null && file.extension == "jar" && file.name.contains("core") && (!file.name.contains("qqandroid"))) {
return file
}
@ -58,27 +43,24 @@ object MiraiCoreLoader {
}
fun loadCore(): String {
MiraiConsole.logger("Fetching Newest Core Version .. ")
val newest = runBlocking {
getNewestVersion()
}
suspend fun versionCheck(){
println("Fetching Newest Core Version .. ")
val newest = getNewestVersion()
val current = getCurrentVersion()
MiraiConsole.logger("Local Version: $current | Newest Version: $newest")
println("Local Core Version: $current | Newest Core Version: $newest")
if (current != newest) {
MiraiConsole.logger("Updating from V$current -> V$newest, this is a force update")
println("Updating Core/Lib from V$current -> V$newest, this is a force update")
cleanCoreAndLib()
runBlocking {
downloadCoreAndLib(newest)
}
MiraiConsole.logger("Download complete")
downloadCoreAndLib(newest)
println("Download Core/Lib complete")
}
MiraiConsole.logger("Loading Core")
loadCoreAndLib()
MiraiConsole.logger("Mirai Core Loaded, current core version $newest")
return newest
}
fun loadCore(){
println("Loading Core")
loadCoreAndLib()
println("Mirai Core and Libraries Loaded")
}
/**
* 判断最新版本
@ -86,14 +68,14 @@ object MiraiCoreLoader {
private suspend fun getNewestVersion(): String {
try {
return """>([0-9])*\.([0-9])*\.([0-9])*/""".toRegex().findAll(
Http.get<String> {
url {
protocol = URLProtocol.HTTPS
host = "jcenter.bintray.com"
path("net/mamoe/mirai-core-qqandroid-jvm/")
}
Http.get<String> {
url {
protocol = URLProtocol.HTTPS
host = "jcenter.bintray.com"
path("net/mamoe/mirai-core-qqandroid-jvm/")
}
).asSequence()
}
).asSequence()
.map { it.value.drop(1).dropLast(1) }
.maxBy {
it.split('.').foldRightIndexed(0) { index: Int, s: String, acc: Int ->
@ -101,9 +83,9 @@ object MiraiCoreLoader {
}
}!!
} catch (e: Exception) {
MiraiConsole.logger("Failed to fetch newest Core version, please seek for help")
println("Failed to fetch newest Core version, please seek for help")
e.printStackTrace()
MiraiConsole.logger("Failed to fetch newest Core version, please seek for help")
println("Failed to fetch newest Core version, please seek for help")
exitProcess(1)
}
}
@ -124,11 +106,8 @@ object MiraiCoreLoader {
private fun cleanCoreAndLib() {
this.coresPath.listFiles()?.forEach {
if (it != null && it.extension == "jar") {
it.delete()
}
}
this.getCore()?.delete()
this.getProtocolLib()?.delete()
}
@ -146,61 +125,52 @@ object MiraiCoreLoader {
}
private suspend fun downloadCoreAndLib(version: String) {
var fileStream = File(coresPath.absolutePath + "/" + "mirai-core-qqandroid-jvm-$version.jar").also {
withContext(Dispatchers.IO) {
it.createNewFile()
}
}.outputStream()
suspend fun downloadRequest(url: String, version: String): ByteReadChannel {
return Http.get<HttpResponse>(url.replace("{version}", version)).content
}
var stream = kotlin.runCatching {
MiraiConsole.logger("Downloading newest Protocol lib from Aliyun")
downloadRequest(Links.libAliyun, version)
}.getOrElse {
kotlin.runCatching {
MiraiConsole.logger("Downloading newest Protocol lib from JCenter")
downloadRequest(Links.libJcenter, version)
}.getOrElse { e ->
MiraiConsole.logger("Failed to download Protocol lib, please seeking for help")
e.printStackTrace()
MiraiConsole.logger("Failed to download Protocol lib, please seeking for help")
exitProcess(1)
coroutineScope {
launch {
tryNTimesOrQuit(3) {
kotlin.runCatching {
println("Downloading newest Protocol lib from Aliyun")
downloadRequest(Links.libAliyun, version)
}.getOrElse {
println("Downloading newest Protocol lib from JCenter")
downloadRequest(Links.libJcenter, version)
}.saveTo("mirai-core-qqandroid-jvm-$version.jar")
}
}
}
withContext(Dispatchers.IO) {
stream.copyTo(fileStream)
fileStream.flush()
}
launch {
tryNTimesOrQuit(3) {
val fileStream = File(contentPath.absolutePath + "/" + "mirai-core-jvm-$version.jar").also {
withContext(Dispatchers.IO) {
it.createNewFile()
}
}.outputStream()
fileStream = File(coresPath.absolutePath + "/" + "mirai-core-jvm-$version.jar").also {
withContext(Dispatchers.IO) {
it.createNewFile()
val stream = try {
println("Downloading newest Mirai Core from Aliyun")
downloadRequest(Links.coreAliyun, version)
} catch (ignored: Exception) {
try {
println("Downloading newest Mirai Core from JCenter")
downloadRequest(Links.coreJcenter, version)
} catch (e: Exception) {
println("Failed to download Mirai Core, please seeking for help")
e.printStackTrace()
println("Failed to download Mirai Core, please seeking for help")
exitProcess(1)
}
}
withContext(Dispatchers.IO) {
stream.copyTo(fileStream)
fileStream.flush()
}
}
}
}.outputStream()
stream = try {
MiraiConsole.logger("Downloading newest Mirai Core from Aliyun")
downloadRequest(Links.coreAliyun, version)
} catch (ignored: Exception) {
try {
MiraiConsole.logger("Downloading newest Mirai Core from JCenter")
downloadRequest(Links.coreJcenter, version)
} catch (e: Exception) {
MiraiConsole.logger("Failed to download Mirai Core, please seeking for help")
e.printStackTrace()
MiraiConsole.logger("Failed to download Mirai Core, please seeking for help")
exitProcess(1)
}
}
withContext(Dispatchers.IO) {
stream.copyTo(fileStream)
fileStream.flush()
}
}
@ -211,8 +181,8 @@ object MiraiCoreLoader {
val coreFile = getCore()!!
val protocolFile = getProtocolLib()!!
MiraiConsole.logger("Core: $coreFile")
MiraiConsole.logger("Protocol: $protocolFile")
println("Core: $coreFile")
println("Protocol: $protocolFile")
val classloader = URLClassLoader(
@ -231,15 +201,12 @@ object MiraiCoreLoader {
println(Class.forName("net.mamoe.mirai.qqandroid.QQAndroid"))
} catch (e: ClassNotFoundException) {
MiraiConsole.logger("Failed to load core, please seek for help")
println("Failed to load core, please seek for help")
e.printStackTrace()
MiraiConsole.logger("Failed to load core, please seek for help")
println("Failed to load core, please seek for help")
exitProcess(1)
}
}
}
}

View File

@ -0,0 +1,58 @@
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.console.wrapper
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.copyTo
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.system.exitProcess
val Http: HttpClient
get() = HttpClient(CIO)
inline fun <R> tryNTimesOrQuit(repeat: Int, block: (Int) -> R){
var lastException: Throwable? = null
repeat(repeat) {
try {
block(it)
return
} catch (e: Throwable) {
if (lastException == null) {
lastException = e
} else lastException!!.addSuppressed(e)
}
}
lastException!!.printStackTrace()
exitProcess(1)
}
suspend inline fun HttpClient.downloadRequest(url: String, version: String): ByteReadChannel {
return this.get<HttpResponse>(url.replace("{version}", version)).content
}
/**
* 只要填content path后面的就可以
*/
suspend fun ByteReadChannel.saveTo(filepath:String){
val fileStream = File(contentPath.absolutePath + "/" + filepath).also {
withContext(Dispatchers.IO) {
it.createNewFile()
}
}.outputStream()
withContext(Dispatchers.IO) {
this@saveTo.copyTo(fileStream)
fileStream.flush()
}
}

View File

@ -0,0 +1,47 @@
package net.mamoe.mirai.console.wrapper
import java.io.File
object LibManager{
val libPath by lazy{
File(contentPath.absolutePath + "/lib/").also {
if(!it.exists()){
it.mkdirs()
}
}
}
fun clearLibs(){
libPath.listFiles()?.forEach {
it.delete()
}
}
/**
* 增加dependency 不是立刻下载
* 全部完成后使用 @link downloadIfNeeded()开始下载
*/
/**
* 由Pom content提供必要依赖
* LibManager会检查所有dependency的dependency
*/
fun addDependencyByPom(pomContent:String){
}
/**
* 普通的增加一个dependency
*/
fun addDependency(){
}
suspend fun downloadIfNeeded(){
}
}

View File

@ -6,11 +6,54 @@
*
* https://github.com/mamoe/mirai/blob/master/LICENSE
*/
@file:Suppress("EXPERIMENTAL_API_USAGE")
package net.mamoe.mirai.console.wrapper
import io.ktor.client.HttpClient
import io.ktor.client.engine.cio.CIO
import io.ktor.client.request.get
import io.ktor.client.statement.HttpResponse
import io.ktor.utils.io.ByteReadChannel
import io.ktor.utils.io.jvm.javaio.copyTo
import kotlinx.coroutines.*
import java.io.File
import kotlin.system.exitProcess
val contentPath by lazy {
File(System.getProperty("user.dir") + "/content/").also {
if (!it.exists()) {
it.mkdirs()
}
}
}
object WrapperMain {
@JvmStatic
fun main(args: Array<String>) {
println("You are running Mirai-Console-Wrapper under " + System.getProperty("user.dir"))
println("Starting version check...")
/**
* ask for type
*/
val type = CONSOLE_PURE
runBlocking {
launch {
CoreUpdator.versionCheck()
}
launch {
ConsoleUpdator.versionCheck(type)
}
}
println("Version check complete, starting Mirai")
}
}
class MiraiClassLoader(
val core:File,
val protocol: File,
val console: File
){
}

View File

@ -17,7 +17,6 @@ import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.CommandSender
import net.mamoe.mirai.console.command.ConsoleCommandSender
import net.mamoe.mirai.console.command.DefaultCommands
import net.mamoe.mirai.console.core.MiraiCoreLoader
import net.mamoe.mirai.console.plugins.PluginManager
import net.mamoe.mirai.console.utils.MiraiConsoleUI
import net.mamoe.mirai.utils.cryptor.ECDH
@ -78,7 +77,6 @@ object MiraiConsole {
logger("Mirai为开源项目请自觉遵守开源项目协议")
logger("Powered by Mamoe Technologies and contributors")
MiraiCoreLoader.loadCore()
/* 加载ECDH */
try {

View File

@ -529,6 +529,7 @@ class TomlConfig internal constructor(content: String) : FileConfigImpl(content)
Toml().read(content).toMap()
)
)
}
override fun serialize(config: ConfigSection): String {

View File

@ -0,0 +1,21 @@
package net.mamoe.mirai.console.plugins
interface ConfigSectionTemplate{
fun autoSave(){
}
}
class MyConfigObject:ConfigSectionTemplate {
class MyTWClass : ConfigSectionTemplate {
}
}