From 93ddbc75106ee8c0aad37dd3fac08ff72a86a313 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Sat, 18 Jan 2020 21:00:21 +0800
Subject: [PATCH 1/4] Specify lambda arg name

---
 .../kotlin/net/mamoe/mirai/plugin/PluginBase.kt  | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
index d1ca57074..f14a5b699 100644
--- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
+++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
@@ -158,25 +158,25 @@ object PluginManager{
 
 
         fun loadPlugin(description: PluginDescription):Boolean{
-            if(!description.noCircularDepend){
+            if (!description.noCircularDepend) {
                 return false.also {
                     logger.error("Failed to load plugin " + description.pluginName + " because it has circular dependency")
                 }
             }
 
             //load depends first
-            description.depends.forEach{
-                if(!pluginsFound.containsKey(it)){
+            description.depends.forEach { dependent ->
+                if (!pluginsFound.containsKey(dependent)) {
                     return false.also { _ ->
-                        logger.error("Failed to load plugin " + description.pluginName + " because it need " + it + " as dependency")
+                        logger.error("Failed to load plugin " + description.pluginName + " because it need " + dependent + " as dependency")
                     }
                 }
-                val depend = pluginsFound[it]!!
+                val depend = pluginsFound[dependent]!!
                 //还没有加载
-                if(!depend.loaded) {
-                    if (!loadPlugin(pluginsFound[it]!!)) {
+                if (!depend.loaded) {
+                    if (!loadPlugin(pluginsFound[dependent]!!)) {
                         return false.also { _ ->
-                            logger.error("Failed to load plugin " + description.pluginName + " because " + it + " as dependency failed to load")
+                            logger.error("Failed to load plugin " + description.pluginName + " because " + dependent + " as dependency failed to load")
                         }
                     }
                 }

From bbe3bf65ea21e2d31f5e220acbde731c5e0e4474 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Sat, 18 Jan 2020 21:03:09 +0800
Subject: [PATCH 2/4] Remove iml

---
 mirai-plugins/image-sender/image-sender.iml | 15 ---------------
 mirai-plugins/mirai-plugins.iml             | 12 ------------
 2 files changed, 27 deletions(-)
 delete mode 100644 mirai-plugins/image-sender/image-sender.iml
 delete mode 100644 mirai-plugins/mirai-plugins.iml

diff --git a/mirai-plugins/image-sender/image-sender.iml b/mirai-plugins/image-sender/image-sender.iml
deleted file mode 100644
index 110223128..000000000
--- a/mirai-plugins/image-sender/image-sender.iml
+++ /dev/null
@@ -1,15 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
-      <sourceFolder url="file://$MODULE_DIR$/src/main/resources" type="java-resource" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="KotlinJavaRuntime (3)" level="project" />
-    <orderEntry type="module" module-name="mirai-console_main" />
-  </component>
-</module>
\ No newline at end of file
diff --git a/mirai-plugins/mirai-plugins.iml b/mirai-plugins/mirai-plugins.iml
deleted file mode 100644
index 245d3429f..000000000
--- a/mirai-plugins/mirai-plugins.iml
+++ /dev/null
@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<module type="JAVA_MODULE" version="4">
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
-    <exclude-output />
-    <content url="file://$MODULE_DIR$">
-      <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
-    </content>
-    <orderEntry type="inheritedJdk" />
-    <orderEntry type="sourceFolder" forTests="false" />
-    <orderEntry type="library" name="KotlinJavaRuntime" level="project" />
-  </component>
-</module>
\ No newline at end of file

From fc99e9722340d779d9b831157e88df153605a6c5 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Sat, 18 Jan 2020 21:17:47 +0800
Subject: [PATCH 3/4] update

---
 mirai-console/build.gradle                    |   3 +-
 mirai-console/src/main/kotlin/MiraiConsole.kt |  45 +++---
 .../net/mamoe/mirai/plugin/PluginBase.kt      | 142 +++++++-----------
 3 files changed, 76 insertions(+), 114 deletions(-)

diff --git a/mirai-console/build.gradle b/mirai-console/build.gradle
index 158cbd8aa..6136f6a9d 100644
--- a/mirai-console/build.gradle
+++ b/mirai-console/build.gradle
@@ -3,7 +3,8 @@ apply plugin: "java"
 
 dependencies {
     api project(':mirai-core')
-    runtimeOnly files(':mirai-core-timpc')
+    api project(':mirai-core-timpc')
+    runtimeOnly files('../mirai-core-timpc/build/classes/kotlin/jvm/main')
     runtimeOnly files('../mirai-core/build/classes/kotlin/jvm/main')
     // classpath is not set correctly by IDE
 }
diff --git a/mirai-console/src/main/kotlin/MiraiConsole.kt b/mirai-console/src/main/kotlin/MiraiConsole.kt
index e6288891e..76b305e38 100644
--- a/mirai-console/src/main/kotlin/MiraiConsole.kt
+++ b/mirai-console/src/main/kotlin/MiraiConsole.kt
@@ -18,34 +18,27 @@ fun main() {
     println("\"login qqnumber qqpassword \" to login a bot")
     println("\"login qq号 qq密码 \" 来登陆一个BOT")
 
+    thread { processNextCommandLine() }
 
-    thread {
-        loop@ while (true) {
-            var command = readLine()
-            if (command != null) {
-                var commandArgs = command.split(" ")
-                when (commandArgs[0]) {
-                    "login" -> {
-                        if (commandArgs.size < 3) {
-                            println("\"login qqnumber qqpassword \" to login a bot")
-                            println("\"login qq号 qq密码 \" 来登陆一个BOT")
-                            continue@loop
-                        }
-                        val qqNumber = commandArgs[1].toLong()
-                        val qqPassword = commandArgs[2]
-                        println("login...")
-                        GlobalScope.launch {
-                            Bot(qqNumber, qqPassword)
-                        }
-                    }
-                }
+    PluginManager.loadPlugins()
+}
+
+tailrec fun processNextCommandLine() {
+    val commandArgs = readLine()?.split(" ") ?: return
+    when (commandArgs[0]) {
+        "login" -> {
+            if (commandArgs.size < 3) {
+                println("\"login qqnumber qqpassword \" to login a bot")
+                println("\"login qq号 qq密码 \" 来登录一个BOT")
+                return processNextCommandLine()
+            }
+            val qqNumber = commandArgs[1].toLong()
+            val qqPassword = commandArgs[2]
+            println("login...")
+            GlobalScope.launch {
+                Bot(qqNumber, qqPassword)
             }
         }
     }
-
-    PluginManager.loadPlugins()
-
-
+    return processNextCommandLine()
 }
-
-
diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
index 7ca1403fe..80fa63eb9 100644
--- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
+++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
@@ -1,16 +1,16 @@
 package net.mamoe.mirai.plugin
 
 import net.mamoe.mirai.utils.DefaultLogger
-import java.io.BufferedReader
+import net.mamoe.mirai.utils.io.encodeToString
 import java.io.File
-import java.io.InputStream
-import java.io.InputStreamReader
-import java.net.JarURLConnection
 import java.net.URL
 import java.util.jar.JarFile
 
 
 abstract class PluginBase constructor() {
+    val dataFolder by lazy {
+        File(PluginManager.pluginsPath + pluginDescription.name).also { it.mkdir() }
+    }
 
     open fun onLoad() {
 
@@ -24,38 +24,27 @@ abstract class PluginBase constructor() {
 
     }
 
-    fun getPluginManager(): PluginManager {
-        return PluginManager
-    }
-
     private lateinit var pluginDescription: PluginDescription
 
     internal fun init(pluginDescription: PluginDescription) {
         this.pluginDescription = pluginDescription
         this.onLoad()
     }
-
-    fun getDataFolder(): File {
-        return File(PluginManager.pluginsPath + pluginDescription.pluginName).also {
-            it.mkdirs()
-        }
-    }
-
 }
 
 class PluginDescription(
-    val pluginName: String,
-    val pluginAuthor: String,
-    val pluginBasePath: String,
-    val pluginVersion: String,
-    val pluginInfo: String,
+    val name: String,
+    val author: String,
+    val basePath: String,
+    val version: String,
+    val info: String,
     val depends: List<String>,//插件的依赖
     internal var loaded: Boolean = false,
     internal var noCircularDepend: Boolean = true
 ) {
 
     override fun toString(): String {
-        return "name: $pluginName\nauthor: $pluginAuthor\npath: $pluginBasePath\nver: $pluginVersion\ninfo: $pluginInfo\ndepends: $depends"
+        return "name: $name\nauthor: $author\npath: $basePath\nver: $version\ninfo: $info\ndepends: $depends"
     }
 
     companion object {
@@ -69,11 +58,11 @@ class PluginDescription(
             var version = "1.0.0"
             val depends = mutableListOf<String>();
 
-            content.forEach{
+            content.forEach {
                 val line = it.trim()
                 val lowercaseLine = line.toLowerCase()
-                if(it.contains(":")) {
-                    when{
+                if (it.contains(":")) {
+                    when {
                         lowercaseLine.startsWith("name") -> {
                             name = line.substringAfter(":").trim()
                         }
@@ -83,26 +72,26 @@ class PluginDescription(
                         lowercaseLine.startsWith("info") || lowercaseLine.startsWith("information") -> {
                             info = line.substringAfter(":").trim()
                         }
-                        lowercaseLine.startsWith("main") || lowercaseLine.startsWith("path") || lowercaseLine.startsWith(
-                            "basepath"
-                        ) -> {
+                        lowercaseLine.startsWith("main") ||
+                                lowercaseLine.startsWith("path") ||
+                                lowercaseLine.startsWith("basepath") -> {
                             basePath = line.substringAfter(":").trim()
                         }
                         lowercaseLine.startsWith("version") || lowercaseLine.startsWith("ver") -> {
                             version = line.substringAfter(":").trim()
                         }
                     }
-                }else if(line.startsWith("-")){
+                } else if (line.startsWith("-")) {
                     depends.add(line.substringAfter("-").trim())
                 }
             }
-            return PluginDescription(name,author,basePath,version,info,depends)
+            return PluginDescription(name, author, basePath, version, info, depends)
         }
     }
 }
 
 
-object PluginManager{
+object PluginManager {
     internal val pluginsPath = System.getProperty("user.dir") + "/plugins/".replace("//", "/").also {
         File(it).mkdirs()
     }
@@ -113,49 +102,37 @@ object PluginManager{
     private val nameToPluginBaseMap: MutableMap<String, PluginBase> = mutableMapOf()
 
 
-
     /**
      * 尝试加载全部插件
      */
-    fun loadPlugins(){
+    fun loadPlugins() {
         val pluginsFound: MutableMap<String, PluginDescription> = mutableMapOf()
         val pluginsLocation: MutableMap<String, JarFile> = mutableMapOf()
 
         File(pluginsPath).listFiles()?.forEach { file ->
-            if (file != null) {
-                if (file.extension == "jar") {
-                    val jar = JarFile(file)
-                    val pluginYml =
-                        jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
-                    if (pluginYml == null) {
-                        logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin")
-                    } else {
-                        val url = URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name)
-                        val jarConnection: JarURLConnection = url
-                            .openConnection() as JarURLConnection
-                        val inputStream: InputStream = jarConnection.getInputStream()
-                        val br = BufferedReader(InputStreamReader(inputStream, "UTF-8"))
-                        var con: String?
-                        val sb = StringBuffer()
-                        while (br.readLine().also { con = it } != null) {
-                            sb.append(con).append("\n")
-                        }
-                        val description = PluginDescription.readFromContent(sb.toString())
-                        println(description)
-                        pluginsFound[description.pluginName] = description
-                        pluginsLocation[description.pluginName] = jar
-                    }
+            if (file != null && file.extension == "jar") {
+                val jar = JarFile(file)
+                val pluginYml =
+                    jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
+                if (pluginYml == null) {
+                    logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin")
+                } else {
+                    val description =
+                        PluginDescription.readFromContent(URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name).openConnection().inputStream.readAllBytes().encodeToString())
+                    println(description)
+                    pluginsFound[description.name] = description
+                    pluginsLocation[description.name] = jar
                 }
             }
         }
 
-        fun checkNoCircularDepends (target:PluginDescription, needDepends: List<String>,existDepends: MutableList<String>) {
+        fun checkNoCircularDepends(target: PluginDescription, needDepends: List<String>, existDepends: MutableList<String>) {
 
             if (!target.noCircularDepend) {
                 return
             }
 
-            existDepends.add(target.pluginName)
+            existDepends.add(target.name)
 
             if (needDepends.any { existDepends.contains(it) }) {
                 target.noCircularDepend = false
@@ -172,65 +149,58 @@ object PluginManager{
 
 
         pluginsFound.values.forEach {
-            checkNoCircularDepends(it,it.depends, mutableListOf())
+            checkNoCircularDepends(it, it.depends, mutableListOf())
         }
 
         //load
 
 
-        fun loadPlugin(description: PluginDescription):Boolean{
+        fun loadPlugin(description: PluginDescription): Boolean {
             if (!description.noCircularDepend) {
-                return false.also {
-                    logger.error("Failed to load plugin " + description.pluginName + " because it has circular dependency")
-                }
+                logger.error("Failed to load plugin " + description.name + " because it has circular dependency")
+                return false
             }
 
             //load depends first
-            description.depends.forEach { dependent ->
-                if (!pluginsFound.containsKey(dependent)) {
-                    return false.also { _ ->
-                        logger.error("Failed to load plugin " + description.pluginName + " because it need " + dependent + " as dependency")
-                    }
+            description.depends.forEach { dependentName ->
+                val dependent = pluginsFound[dependentName]
+                if (dependent == null) {
+                    logger.error("Failed to load plugin " + description.name + " because it need " + dependentName + " as dependency")
+                    return false
                 }
-                val depend = pluginsFound[dependent]!!
                 //还没有加载
-                if (!depend.loaded) {
-                    if (!loadPlugin(pluginsFound[dependent]!!)) {
-                        return false.also { _ ->
-                            logger.error("Failed to load plugin " + description.pluginName + " because " + dependent + " as dependency failed to load")
-                        }
-                    }
+                if (!dependent.loaded && !loadPlugin(dependent)) {
+                    logger.error("Failed to load plugin " + description.name + " because " + dependentName + " as dependency failed to load")
+                    return false
                 }
             }
             //在这里所有的depends都已经加载了
 
 
             //real load
-            logger.info("loading plugin " + description.pluginName)
+            logger.info("loading plugin " + description.name)
 
             try {
-                this.javaClass.classLoader.loadClass(description.pluginBasePath)
+                this.javaClass.classLoader.loadClass(description.basePath)
                 return try {
                     val subClass = javaClass.asSubclass(PluginBase::class.java)
                     val plugin: PluginBase = subClass.getDeclaredConstructor().newInstance()
                     description.loaded = true
-                    logger.info("successfully loaded plugin " + description.pluginName)
-                    logger.info(description.pluginInfo)
+                    logger.info("successfully loaded plugin " + description.name)
+                    logger.info(description.info)
 
-                    nameToPluginBaseMap[description.pluginName] = plugin
+                    nameToPluginBaseMap[description.name] = plugin
                     plugin.init(description)
 
                     true
                 } catch (e: ClassCastException) {
-                    false.also {
-                        logger.error("failed to load plugin " + description.pluginName + " , Main class does not extends PluginBase ")
-                    }
+                    logger.error("failed to load plugin " + description.name + " , Main class does not extends PluginBase ")
+                    false
                 }
             } catch (e: ClassNotFoundException) {
                 e.printStackTrace()
-                return false.also {
-                    logger.error("failed to load plugin " + description.pluginName + " , Main class not found under " + description.pluginBasePath)
-                }
+                logger.error("failed to load plugin " + description.name + " , Main class not found under " + description.basePath)
+                return false
             }
         }
 
@@ -240,8 +210,6 @@ object PluginManager{
     }
 
 
-
-
 }
 
 

From 4f305ebd58f233f845badca465e72607fbdbd5b0 Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Sat, 18 Jan 2020 21:18:11 +0800
Subject: [PATCH 4/4] update

---
 .../src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt        | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
index 80fa63eb9..e75037179 100644
--- a/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
+++ b/mirai-console/src/main/kotlin/net/mamoe/mirai/plugin/PluginBase.kt
@@ -115,7 +115,7 @@ object PluginManager {
                 val pluginYml =
                     jar.entries().asSequence().filter { it.name.toLowerCase().contains("plugin.yml") }.firstOrNull()
                 if (pluginYml == null) {
-                    logger.info("plugin.yml not found in jar " + jar.name + ", it will not be consider as a Plugin")
+                    logger.info("plugin.yml not found in jar " + jar.name + ", it will not be considered as a Plugin")
                 } else {
                     val description =
                         PluginDescription.readFromContent(URL("jar:file:" + file.absoluteFile + "!/" + pluginYml.name).openConnection().inputStream.readAllBytes().encodeToString())