mirror of
https://github.com/mamoe/mirai.git
synced 2025-04-25 21:23:55 +08:00
wrapper rewrite
This commit is contained in:
parent
ac125b22d2
commit
90d074a1dd
gradle.properties
mirai-console-wrapper
build.gradle.kts
src/main/kotlin/net/mamoe/mirai/console/wrapper
@ -1,21 +1,21 @@
|
||||
# style guide
|
||||
kotlin.code.style=official
|
||||
# config
|
||||
miraiVersion=0.29.1
|
||||
miraiConsoleVersion=0.3.6
|
||||
miraiConsoleWrapperVersion=0.1.3
|
||||
miraiVersion=0.30.0
|
||||
miraiConsoleVersion=0.3.7
|
||||
miraiConsoleWrapperVersion=0.1.4
|
||||
kotlin.incremental.multiplatform=true
|
||||
kotlin.parallel.tasks.in.project=true
|
||||
# kotlin
|
||||
kotlinVersion=1.3.70
|
||||
kotlinVersion=1.4-M1
|
||||
# kotlin libraries
|
||||
serializationVersion=0.20.0
|
||||
coroutinesVersion=1.3.4
|
||||
atomicFuVersion=0.14.1
|
||||
serializationVersion=0.20.0-1.4-M1
|
||||
coroutinesVersion=1.3.5-1.4-M1
|
||||
atomicFuVersion=0.14.2-1.4-M1
|
||||
kotlinXIoVersion=0.1.16
|
||||
coroutinesIoVersion=0.1.16
|
||||
# utility
|
||||
ktorVersion=1.3.2
|
||||
ktorVersion=1.3.2-1.4-M1
|
||||
klockVersion=1.7.0
|
||||
# gradle plugin
|
||||
protobufJavaVersion=3.10.0
|
||||
|
@ -80,6 +80,8 @@ dependencies {
|
||||
api(group = "org.yaml", name = "snakeyaml", version = "1.25")
|
||||
api(group = "com.moandjiezana.toml", name = "toml4j", version = "0.7.2")
|
||||
|
||||
api(group = "com.github.tomas-langer.cli", name="cli-progress", version="1.0.0")
|
||||
|
||||
}
|
||||
|
||||
val miraiConsoleWrapperVersion: String by project.ext
|
||||
|
@ -51,8 +51,9 @@ internal object ConsoleUpdater {
|
||||
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")
|
||||
MiraiDownloader.addTask(
|
||||
"https://raw.githubusercontent.com/mamoe/mirai-repo/master/shadow/${getProjectName()}/${getProjectName()}-$newest.jar",getContent("${getProjectName()}-$newest.jar")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -102,11 +103,12 @@ internal object ConsoleUpdater {
|
||||
}
|
||||
|
||||
private suspend fun downloadConsole(version: String) {
|
||||
|
||||
/*
|
||||
tryNTimesOrQuit(3, "Failed to download Console, please seek for help") {
|
||||
Http.downloadMavenArchive("net/mamoe", getProjectName(), version)
|
||||
.saveToContent("${getProjectName()}-$version.jar")
|
||||
}
|
||||
LibManager.clearLibs()
|
||||
LibManager.addDependencyRequest("net/mamoe", getProjectName(), version)
|
||||
*/
|
||||
}
|
||||
}
|
@ -13,10 +13,7 @@ package net.mamoe.mirai.console.wrapper
|
||||
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.http.URLProtocol
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
import kotlin.math.pow
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
@ -31,15 +28,6 @@ internal object CoreUpdater {
|
||||
return null
|
||||
}
|
||||
|
||||
fun getCore(): File? {
|
||||
contentPath.listFiles()?.forEach { file ->
|
||||
if (file != null && file.extension == "jar" && file.name.contains("core") && (!file.name.contains("qqandroid"))) {
|
||||
return file
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
suspend fun versionCheck() {
|
||||
println("Fetching Newest Core Version .. ")
|
||||
@ -47,19 +35,13 @@ internal object CoreUpdater {
|
||||
val current = getCurrentVersion()
|
||||
println("Local Core Version: $current | Newest Core Version: $newest")
|
||||
if (current != newest) {
|
||||
println("Updating Core/Lib from V$current -> V$newest, this is a force update")
|
||||
cleanCoreAndLib()
|
||||
downloadCoreAndLib(newest)
|
||||
println("Download Core/Lib complete")
|
||||
println("Updating shadowed-core from V$current -> V$newest, this is a force update")
|
||||
this.getProtocolLib()?.delete()
|
||||
MiraiDownloader
|
||||
.addTask("https://raw.githubusercontent.com/mamoe/mirai-repo/master/shadow/mirai-core-qqandroid/mirai-core-qqandroid-$newest.jar", getContent("mirai-core-qqandroid-jvm-$newest.jar"))
|
||||
}
|
||||
}
|
||||
|
||||
fun loadCore() {
|
||||
println("Loading Core")
|
||||
loadCoreAndLib()
|
||||
println("Mirai Core and Libraries Loaded")
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断最新版本
|
||||
* */
|
||||
@ -93,8 +75,7 @@ internal object CoreUpdater {
|
||||
* 默认返回 "0.0.0"
|
||||
*/
|
||||
fun getCurrentVersion(): String {
|
||||
val file = getProtocolLib()
|
||||
if (file == null || getCore() == null) return "0.0.0"
|
||||
val file = getProtocolLib() ?: return "0.0.0"
|
||||
val numberVersion = """([0-9])*\.([0-9])*\.([0-9])*""".toRegex().find(file.name)?.value
|
||||
if (numberVersion != null) {
|
||||
return numberVersion + file.name.substringAfter(numberVersion).substringBefore(".jar")
|
||||
@ -103,13 +84,16 @@ internal object CoreUpdater {
|
||||
}
|
||||
|
||||
|
||||
private fun cleanCoreAndLib() {
|
||||
this.getCore()?.delete()
|
||||
this.getProtocolLib()?.delete()
|
||||
}
|
||||
|
||||
/*
|
||||
private suspend fun downloadCore(version: String) {
|
||||
/**
|
||||
* from github
|
||||
*/
|
||||
|
||||
|
||||
private suspend fun downloadCoreAndLib(version: String) {
|
||||
/**
|
||||
* from jcenter
|
||||
coroutineScope {
|
||||
launch {
|
||||
tryNTimesOrQuit(3, "Failed to download newest Protocol lib, please seek for help") {
|
||||
@ -124,48 +108,13 @@ internal object CoreUpdater {
|
||||
.saveToContent("mirai-core-jvm-$version.jar")
|
||||
}
|
||||
}
|
||||
|
||||
launch {
|
||||
LibManager.clearLibs()
|
||||
LibManager.addDependencyRequest("net/mamoe", "mirai-core-jvm", version)
|
||||
LibManager.addDependencyRequest("net/mamoe", "mirai-core-qqandroid-jvm", version)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
|
||||
private fun loadCoreAndLib() {
|
||||
try {
|
||||
|
||||
val coreFile = getCore()!!
|
||||
val protocolFile = getProtocolLib()!!
|
||||
|
||||
println("Core: $coreFile")
|
||||
println("Protocol: $protocolFile")
|
||||
|
||||
val classloader = URLClassLoader(
|
||||
arrayOf(coreFile.toURI().toURL(), protocolFile.toURI().toURL()),
|
||||
this.javaClass.classLoader
|
||||
)
|
||||
ClassLoader.getSystemClassLoader()
|
||||
// this.javaClass.classLoader.
|
||||
println(classloader.loadClass("net.mamoe.mirai.BotFactory"))
|
||||
println(classloader.loadClass("net.mamoe.mirai.qqandroid.QQAndroid"))
|
||||
println(classloader.loadClass("net.mamoe.mirai.utils.cryptor.ECDHJvmKt"))
|
||||
|
||||
val a = classloader.loadClass("net.mamoe.mirai.qqandroid.QQAndroid").kotlin.objectInstance!!
|
||||
println(a::class.java)
|
||||
|
||||
println(Class.forName("net.mamoe.mirai.qqandroid.QQAndroid"))
|
||||
|
||||
} catch (e: ClassNotFoundException) {
|
||||
println("Failed to load core, please seek for help")
|
||||
e.printStackTrace()
|
||||
println("Failed to load core, please seek for help")
|
||||
exitProcess(1)
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
@ -17,7 +17,6 @@ internal val Http: HttpClient = HttpClient(CIO)
|
||||
|
||||
internal inline fun <R> tryNTimesOrQuit(repeat: Int, errorHint: String, block: (Int) -> R) {
|
||||
var lastException: Throwable? = null
|
||||
|
||||
repeat(repeat) {
|
||||
try {
|
||||
block(it)
|
||||
@ -34,7 +33,6 @@ internal inline fun <R> tryNTimesOrQuit(repeat: Int, errorHint: String, block: (
|
||||
exitProcess(1)
|
||||
}
|
||||
|
||||
|
||||
internal suspend inline fun HttpClient.downloadRequest(url: String): ByteReadChannel {
|
||||
return with(this.get<HttpResponse>(url)) {
|
||||
if (this.status.value == 404 || this.status.value == 403) {
|
||||
@ -140,3 +138,6 @@ internal suspend fun ByteReadChannel.saveToContent(filepath: String) {
|
||||
|
||||
|
||||
|
||||
internal fun getContent(filepath: String):File{
|
||||
return File(contentPath.absolutePath + "/" + filepath)
|
||||
}
|
@ -1,121 +0,0 @@
|
||||
package net.mamoe.mirai.console.wrapper
|
||||
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
||||
object LibManager{
|
||||
|
||||
val libPath by lazy{
|
||||
File(contentPath.absolutePath + "/lib/").also {
|
||||
if(!it.exists()){
|
||||
it.mkdirs()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 开关
|
||||
* 当前版本不写dynamic加载lib
|
||||
*/
|
||||
val dynamic = false;
|
||||
|
||||
fun clearLibs(){
|
||||
if(!dynamic){
|
||||
return;
|
||||
}
|
||||
libPath.listFiles()?.forEach {
|
||||
it.delete()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 增加dependency 不是立刻下载
|
||||
* 全部完成后使用 @link downloadIfNeeded()开始下载
|
||||
*/
|
||||
|
||||
/**
|
||||
* 由Pom Path提供必要依赖
|
||||
* LibManager会进行下载和递归处理
|
||||
*/
|
||||
suspend fun addDependencyRequest(
|
||||
group: String,
|
||||
project: String,
|
||||
version: String
|
||||
){
|
||||
if(!dynamic){
|
||||
return;
|
||||
}
|
||||
var pom:String? = null
|
||||
if(project.contains("maven") && project.contains("plugin")){
|
||||
return
|
||||
}
|
||||
if(project.contains("toplink-essentials") || project.contains("ejb") ||project.contains("glassfish-embedded-all") || project.contains("maven-bundle-plugin") || project.contains("jetty") || project.contains("plexus-component-annotations") || project.contains("slf4j") || project.contains("sisu-inject-plexus") || project.contains("maven-remote-resources-plugin") || project.contains("easymock") || project.contains("junit") || project.contains("log4j") || project.contains("doxia-logging-api") || project.contains("maven-enforcer-plugin") || project.contains("maven-plugin") || project.contains("maven-artifact") || project.contains("maven-core") || project.contains("cglib") || project.contains("spring-core")){
|
||||
return
|
||||
}
|
||||
tryNTimesOrQuit(3, "Failed to find dependency for $project") {
|
||||
pom = Http.downloadMavenPomAsString(
|
||||
group, project, version
|
||||
)
|
||||
}
|
||||
addDependency(group,project,version)
|
||||
if(pom == null){
|
||||
println("Failed to load dependency POM")
|
||||
return
|
||||
}
|
||||
pom!!.replace("\n","").split("</dependency>").forEach {
|
||||
if(it.contains("<dependency>")) {
|
||||
val dependencyInfo = it.replace("<dependency>","")
|
||||
if(dependencyInfo.contains("<groupId>") && dependencyInfo.contains("<artifactId>") && dependencyInfo.contains("<version>")) {
|
||||
val groupName =
|
||||
dependencyInfo.substringAfter("<groupId>").substringBefore("</groupId>").replace(".", "/")
|
||||
.removeSuffix("/")
|
||||
val projectName = dependencyInfo.substringAfter("<artifactId>").substringBefore("</artifactId>")
|
||||
val versionName = dependencyInfo.substringAfter("<version>").substringBefore("</version>")
|
||||
if (!versionName.contains("{")) {
|
||||
if (addDependency(groupName, projectName, versionName)) {
|
||||
addDependencyRequest(groupName, projectName, versionName)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 普通的增加一个dependency
|
||||
*/
|
||||
private val dependency = HashSet<String>()
|
||||
fun addDependency(
|
||||
group: String,
|
||||
project: String,
|
||||
version: String
|
||||
):Boolean{
|
||||
if(!dynamic){
|
||||
return false;
|
||||
}
|
||||
if(project.contains("maven") && project.contains("plugin")){
|
||||
return true
|
||||
}
|
||||
if(project.contains("toplink-essentials") ||project.contains("ejb") || project.contains("glassfish-embedded-all") || project.contains("maven-bundle-plugin") || project.contains("jetty") || project.contains("slf4j") || project.contains("sisu-inject-plexus") || project.contains("maven-remote-resources-plugin") || project.contains("easymock") || project.contains("junit") || project.contains("log4j") || project.contains("doxia-logging-api") || project.contains("maven-enforcer-plugin") || project.contains("maven-plugin") || project.contains("maven-artifact") || project.contains("maven-core") || project.contains("cglib") || project.contains("spring-core")){
|
||||
return true
|
||||
}
|
||||
val id = "${group
|
||||
.replace(".","/")
|
||||
.removeSuffix("/")
|
||||
}-$project:$version"
|
||||
if(dependency.contains(id)){
|
||||
return false
|
||||
}
|
||||
println(id)
|
||||
dependency.add(id)
|
||||
return true
|
||||
}
|
||||
|
||||
suspend fun downloadIfNeeded(){
|
||||
this.dependency.forEach {
|
||||
println(it)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,128 @@
|
||||
package net.mamoe.mirai.console.wrapper
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.io.InputStream
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.system.exitProcess
|
||||
|
||||
|
||||
internal object MiraiDownloader{
|
||||
private val tasks = mutableMapOf<String,File>()
|
||||
|
||||
fun addTask(
|
||||
fromUrl: String,
|
||||
to: File
|
||||
){
|
||||
tasks[fromUrl] = to
|
||||
}
|
||||
|
||||
suspend fun downloadIfNeed(){
|
||||
if(tasks.isNotEmpty()){
|
||||
MiraiDownloaderImpl(EmptyCoroutineContext, tasks).waitUntilFinish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private class MiraiDownloaderImpl(
|
||||
override val coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
tasks: Map<String, File>
|
||||
):CoroutineScope {
|
||||
|
||||
val bar = MiraiDownloaderProgressBar()
|
||||
|
||||
var totalDownload = AtomicInteger(0)
|
||||
var totalSize = AtomicInteger(0)
|
||||
|
||||
private var isDownloadFinish: Job
|
||||
|
||||
init {
|
||||
println("Mirai Downloader")
|
||||
isDownloadFinish = this.async {
|
||||
tasks.forEach {
|
||||
this.launch {
|
||||
downloadTask(it.key, it.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun waitUntilFinish(){
|
||||
while (!isDownloadFinish.isCompleted){
|
||||
bar.update(totalDownload.get().toFloat()/totalSize.get(),(totalSize.get()/(1024*1024)).toString() + "MB" )
|
||||
delay(50)
|
||||
}
|
||||
bar.update(1F,"Complete")
|
||||
bar.complete()
|
||||
}
|
||||
|
||||
|
||||
@Throws(Exception::class)
|
||||
private suspend fun downloadTask(fromUrl: String, file: File) {
|
||||
withContext(Dispatchers.IO) {
|
||||
try {
|
||||
val url = URL(fromUrl)
|
||||
val con: HttpURLConnection = url.openConnection() as HttpURLConnection
|
||||
val input: InputStream = con.inputStream
|
||||
totalSize.addAndGet(con.contentLength)
|
||||
val outputStream = FileOutputStream(file)
|
||||
|
||||
var len = -1
|
||||
val buff = ByteArray(1024)
|
||||
while (input.read(buff).also { len = it } != -1) {
|
||||
totalDownload.addAndGet(len)
|
||||
outputStream.write(buff, 0, len);
|
||||
}
|
||||
}catch (e: Exception){
|
||||
bar.update(1F,"Failed")
|
||||
bar.complete()
|
||||
println("Failed to download resources from " + fromUrl + " reason " + e.message)
|
||||
e.printStackTrace()
|
||||
println("Failed to download resources from " + fromUrl + " reason " + e.message)
|
||||
println("Please Seek For Help")
|
||||
exitProcess(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class MiraiDownloaderProgressBar(){
|
||||
|
||||
private fun reset() {
|
||||
print('\r')
|
||||
}
|
||||
|
||||
private val barLen = 40
|
||||
|
||||
fun update(rate: Float, message: String) {
|
||||
reset()
|
||||
print("Progress: ")
|
||||
val len = (rate * barLen).toInt()
|
||||
for (i in 0 until len) {
|
||||
print("#")
|
||||
}
|
||||
for (i in 0 until barLen - len) {
|
||||
print(" ")
|
||||
}
|
||||
print(" | $message")
|
||||
}
|
||||
|
||||
fun complete(){
|
||||
println()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -65,21 +65,26 @@ object WrapperMain {
|
||||
ConsoleUpdater.versionCheck(type)
|
||||
}
|
||||
}
|
||||
|
||||
runBlocking {
|
||||
MiraiDownloader.downloadIfNeed()
|
||||
}
|
||||
|
||||
println("Version check complete, starting Mirai")
|
||||
println("Core :" + CoreUpdater.getCore()!!)
|
||||
println("Protocol:" + CoreUpdater.getProtocolLib()!!)
|
||||
println("Console :" + ConsoleUpdater.getFile()!!)
|
||||
println("Root :" + System.getProperty("user.dir") + "/")
|
||||
println("shadow-Protocol:" + CoreUpdater.getProtocolLib()!!)
|
||||
println("Console :" + ConsoleUpdater.getFile()!!)
|
||||
println("Root :" + System.getProperty("user.dir") + "/")
|
||||
|
||||
val loader = MiraiClassLoader(
|
||||
CoreUpdater.getCore()!!,
|
||||
CoreUpdater.getProtocolLib()!!,
|
||||
ConsoleUpdater.getFile()!!,
|
||||
this.javaClass.classLoader
|
||||
)
|
||||
|
||||
loader.loadClass("net.mamoe.mirai.BotFactoryJvm")
|
||||
|
||||
when (type) {
|
||||
CONSOLE_PURE -> {
|
||||
loader.loadClass("net.mamoe.mirai.BotFactoryJvm")
|
||||
loader.loadClass(
|
||||
"net.mamoe.mirai.console.pure.MiraiConsolePureLoader"
|
||||
).getMethod("load", String::class.java, String::class.java)
|
||||
@ -90,12 +95,10 @@ object WrapperMain {
|
||||
}
|
||||
|
||||
class MiraiClassLoader(
|
||||
core:File,
|
||||
protocol: File,
|
||||
console: File,
|
||||
parent: ClassLoader
|
||||
): URLClassLoader(arrayOf(
|
||||
core.toURI().toURL(),
|
||||
protocol.toURI().toURL(),
|
||||
console.toURI().toURL()
|
||||
), parent)
|
||||
|
Loading…
Reference in New Issue
Block a user