diff --git a/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/ConsoleUpdator.kt b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/ConsoleUpdator.kt new file mode 100644 index 000000000..72204655d --- /dev/null +++ b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/ConsoleUpdator.kt @@ -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>() { + 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 { + 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" + }) + + } + } + + + +} \ No newline at end of file diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/core/MiraiCoreLoader.kt b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/CoreUpdator.kt similarity index 52% rename from mirai-console/src/main/kotlin/net/mamoe/mirai/console/core/MiraiCoreLoader.kt rename to mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/CoreUpdator.kt index aaefb328b..e999d81e2 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/core/MiraiCoreLoader.kt +++ b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/CoreUpdator.kt @@ -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 { - url { - protocol = URLProtocol.HTTPS - host = "jcenter.bintray.com" - path("net/mamoe/mirai-core-qqandroid-jvm/") - } + Http.get { + 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(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) } } -} - - - +} \ No newline at end of file diff --git a/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/Downloader.kt b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/Downloader.kt new file mode 100644 index 000000000..d5877d77e --- /dev/null +++ b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/Downloader.kt @@ -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 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(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() + } +} + diff --git a/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/LibManager.kt b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/LibManager.kt new file mode 100644 index 000000000..9e14eb849 --- /dev/null +++ b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/LibManager.kt @@ -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(){ + + } + +} \ No newline at end of file diff --git a/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/WrapperMain.kt b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/WrapperMain.kt index 94989df9f..dbb54b2b4 100644 --- a/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/WrapperMain.kt +++ b/mirai-console-wrapper/src/main/kotlin/net/mamoe/mirai/console/wrapper/WrapperMain.kt @@ -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) { + 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 +){ + } \ No newline at end of file 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 044e74efd..42a55aaad 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 @@ -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 { diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSection.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSection.kt index 995c8fd1b..72c567109 100644 --- a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSection.kt +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSection.kt @@ -529,6 +529,7 @@ class TomlConfig internal constructor(content: String) : FileConfigImpl(content) Toml().read(content).toMap() ) ) + } override fun serialize(config: ConfigSection): String { diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSectionTemplate.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSectionTemplate.kt new file mode 100644 index 000000000..b9d4058d4 --- /dev/null +++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugins/ConfigSectionTemplate.kt @@ -0,0 +1,21 @@ +package net.mamoe.mirai.console.plugins + +interface ConfigSectionTemplate{ + + + fun autoSave(){ + + } + + +} + + + +class MyConfigObject:ConfigSectionTemplate { + + class MyTWClass : ConfigSectionTemplate { + + } + +} \ No newline at end of file