3 Commits
v1.0 ... master

Author SHA1 Message Date
7f4945fc34 更新帮助
优化说明
2022-03-30 17:57:50 +08:00
3958c2a385 更新使用说明 2022-03-30 17:46:12 +08:00
646a340171 更新到v1.1.0
支持执行引用的代码(含pastebin网址)
执行引用的代码时,参数可包含输入
2022-03-30 17:28:19 +08:00
6 changed files with 109 additions and 54 deletions

View File

@@ -1,31 +1,55 @@
# JCC - J Compiler Collection # JCC - J Compiler Collection
## 基于Glot接口的mirai-console在线编译器插件 ## 基于Glot接口的mirai-console在线编译器插件
### 使用帮助 ## `run`命令原型
``` - `run <language> <code>`
run <language> <code|pastebin> [stdin] - `run <language> <pastebinUrl> [stdin]`
例如run python print("Hello world") - `引用消息: run <language> [stdin]`
支持从pastebin.ubuntu.com中运行代码 ### 参数说明
run c https://pastebin.ubuntu.com/p/KhBB7ZjVbD/ | 参数 | 说明 | 示例 | 备注 |
你还可以在后面跟随标准输入仅pastebin支持 | ---- | ---- | --- | --- |
run c https://pastebin.ubuntu.com/p/S2PyvRqJNf/ 1 2 3 4 | `language` | 编程语言 | `python` | 用`/jcc list`列出所有支持的语言 |
其它指令: | `code` | 代码 | `print("Hello world")` | 要运行的代码,支持换行 |
/jcc help # 帮助 | `pastebinUrl` | pastebin地址 | `https://pastebin.ubuntu.com/p/KhBB7ZjVbD/` | 需要在 [pastebin](https://pastebin.ubuntu.com/) 上传代码 |
/jcc list # 列出所有支持的编程语言 | `stdin` | 标准输入 | `1 2 3 4 5` | 可选 用于`scanf`之类 |
/jcc template <language> # 获取指定语言的模板
``` ## 使用示例
### 直接使用
`run python print("Hello world")`
### 从 [pastebinUrl](https://pastebin.ubuntu.com/) 运行代码:
`run c https://pastebin.ubuntu.com/p/KhBB7ZjVbD/`
### 从 引用 执行代码:
> 引用: print("Hello world")
`run python`
### 支持运行程序带输入:
#### 例1
`run c https://pastebin.ubuntu.com/p/S2PyvRqJNf/ 1 2 3 4 5`
#### 例2
> 引用: https://pastebin.ubuntu.com/p/S2PyvRqJNf/
`run c 1 2 3 4 5`
## 其他指令
- /jcc help # 帮助
- /jcc list # 列出所有支持的编程语言
- /jcc template <language> # 获取指定语言的模板
--- ---
### 使用方法 ## 插件使用方法
本插件基于[Mirai-Console](https://github.com/mamoe/mirai-console)运行,您可以通过阅读[Mirai用户手册](https://docs.mirai.mamoe.net/UserManual.html)来了解如何安装、启动机器人。 本插件基于[Mirai-Console](https://github.com/mamoe/mirai-console)运行,您可以通过阅读[Mirai用户手册](https://docs.mirai.mamoe.net/UserManual.html)来了解如何安装、启动机器人。
`MiraiConsole`成功启动后,只需要将本项目[发布](https://github.com/jie65535/mirai-console-jcc-plugin/releases)的`.jar`文件放入`.\plugins\`目录下即可加载插件。 `MiraiConsole`成功启动后,只需要将本项目[发布](https://github.com/jie65535/mirai-console-jcc-plugin/releases)的`.jar`文件放入`.\plugins\`目录下即可加载插件。
### 发布地址 ## 发布地址
本插件在[Mirai论坛](https://mirai.mamoe.net/)发布,[点击这里](https://mirai.mamoe.net/topic/463/jcc-%E5%9F%BA%E4%BA%8Emirai-console%E7%9A%84%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%E6%8F%92%E4%BB%B6)查看 本插件在[Mirai论坛](https://mirai.mamoe.net/)发布,[点击这里](https://mirai.mamoe.net/topic/463/jcc-%E5%9F%BA%E4%BA%8Emirai-console%E7%9A%84%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%E6%8F%92%E4%BB%B6)查看
### 反馈 ## 反馈
如使用或安装插件过程中遇到非本插件功能问题,您首先应该在[Mirai论坛](https://mirai.mamoe.net/)中搜索解决方案,若未解决,可以在[本项目的主题贴](https://mirai.mamoe.net/topic/463/jcc-%E5%9F%BA%E4%BA%8Emirai-console%E7%9A%84%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%E6%8F%92%E4%BB%B6)中回帖提问。 如使用或安装插件过程中遇到非本插件功能问题,您首先应该在[Mirai论坛](https://mirai.mamoe.net/)中搜索解决方案,若未解决,可以在[本项目的主题贴](https://mirai.mamoe.net/topic/463/jcc-%E5%9F%BA%E4%BA%8Emirai-console%E7%9A%84%E5%9C%A8%E7%BA%BF%E7%BC%96%E8%AF%91%E6%8F%92%E4%BB%B6)中回帖提问。
如果是插件本身的问题或漏洞,您可以向我提交一个[issue](https://github.com/jie65535/mirai-console-jcc-plugin/issues)。若您有能力且愿意帮助我修复这些问题,请提交[Pull request](https://github.com/jie65535/mirai-console-jcc-plugin/pulls)。 如果是插件本身的问题或漏洞,您可以向我提交一个[issue](https://github.com/jie65535/mirai-console-jcc-plugin/issues)。若您有能力且愿意帮助我修复这些问题,请提交[Pull request](https://github.com/jie65535/mirai-console-jcc-plugin/pulls)。

View File

@@ -7,7 +7,7 @@ plugins {
} }
group = "top.jie65535" group = "top.jie65535"
version = "1.0" version = "1.1.0"
repositories { repositories {
maven("https://maven.aliyun.com/repository/public") maven("https://maven.aliyun.com/repository/public")

View File

@@ -35,8 +35,6 @@ object GlotAPI {
@Serializable @Serializable
data class RunResult(val stdout: String, val stderr: String, val error: String) data class RunResult(val stdout: String, val stderr: String, val error: String)
private var languages: List<Language>? = null
private val templateFiles: MutableMap<String, CodeFile> = mutableMapOf()
// val fileExtensions: Map<String, String> = mapOf("assembly" to "asm", "ats" to "dats", "bash" to "sh", "c" to "c", "clojure" to "clj", "cobol" to "cob", "coffeescript" to "coffee", "cpp" to "cpp", "crystal" to "cr", "csharp" to "cs", "d" to "d", "elixir" to "ex", "elm" to "elm", "erlang" to "erl", "fsharp" to "fs", "go" to "go", "groovy" to "groovy", "haskell" to "hs", "idris" to "idr", "java" to "java", "javascript" to "js", "julia" to "jl", "kotlin" to "kt", "lua" to "lua", "mercury" to "m", "nim" to "nim", "nix" to "nix", "ocaml" to "ml", "perl" to "pl", "php" to "php", "python" to "py", "raku" to "raku", "ruby" to "rb", "rust" to "rs", "scala" to "scala", "swift" to "swift", "typescript" to "ts", "plaintext" to "txt", ) // val fileExtensions: Map<String, String> = mapOf("assembly" to "asm", "ats" to "dats", "bash" to "sh", "c" to "c", "clojure" to "clj", "cobol" to "cob", "coffeescript" to "coffee", "cpp" to "cpp", "crystal" to "cr", "csharp" to "cs", "d" to "d", "elixir" to "ex", "elm" to "elm", "erlang" to "erl", "fsharp" to "fs", "go" to "go", "groovy" to "groovy", "haskell" to "hs", "idris" to "idr", "java" to "java", "javascript" to "js", "julia" to "jl", "kotlin" to "kt", "lua" to "lua", "mercury" to "m", "nim" to "nim", "nix" to "nix", "ocaml" to "ml", "perl" to "pl", "php" to "php", "python" to "py", "raku" to "raku", "ruby" to "rb", "rust" to "rs", "scala" to "scala", "swift" to "swift", "typescript" to "ts", "plaintext" to "txt", )
/** /**
@@ -56,10 +54,10 @@ object GlotAPI {
* ``` * ```
*/ */
fun listLanguages(): List<Language> { fun listLanguages(): List<Language> {
if (languages == null) { if (JccPluginData.languages.isEmpty()) {
languages = Json.decodeFromString(HttpUtil.get(URL_LIST_LANGUAGES)) ?: throw Exception("未获取到任何数据") JccPluginData.languages = Json.decodeFromString(HttpUtil.get(URL_LIST_LANGUAGES)) ?: throw Exception("未获取到任何数据")
} }
return languages!! return JccPluginData.languages
} }
/** /**
@@ -83,13 +81,13 @@ object GlotAPI {
*/ */
fun getTemplateFile(language: String): CodeFile { fun getTemplateFile(language: String): CodeFile {
val lang = getSupport(language) val lang = getSupport(language)
if (templateFiles.containsKey(lang.name)) if (JccPluginData.templateFiles.containsKey(lang.name))
return templateFiles[lang.name]!! return JccPluginData.templateFiles[lang.name]!!
val document = HttpUtil.getDocument(URL_NEW + lang.name) val document = HttpUtil.getDocument(URL_NEW + lang.name)
val filename = HttpUtil.documentSelect(document, ".filename").firstOrNull()?.text() ?: throw Exception("无法获取文件名") val filename = HttpUtil.documentSelect(document, ".filename").firstOrNull()?.text() ?: throw Exception("无法获取文件名")
val fileContent = HttpUtil.documentSelect(document, "#editor-1").text() ?: throw Exception("无法获取模板文件内容") val fileContent = HttpUtil.documentSelect(document, "#editor-1").text() ?: throw Exception("无法获取模板文件内容")
val templateFile = CodeFile(filename, fileContent) val templateFile = CodeFile(filename, fileContent)
templateFiles[lang.name] = templateFile JccPluginData.templateFiles[lang.name] = templateFile
return templateFile return templateFile
} }

View File

@@ -1,20 +1,23 @@
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister
import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.load
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group
import net.mamoe.mirai.contact.isBotMuted import net.mamoe.mirai.contact.isBotMuted
import net.mamoe.mirai.event.events.GroupMessageEvent
import net.mamoe.mirai.event.events.MessageEvent
import net.mamoe.mirai.event.globalEventChannel import net.mamoe.mirai.event.globalEventChannel
import net.mamoe.mirai.event.subscribeMessages import net.mamoe.mirai.event.subscribeMessages
import net.mamoe.mirai.message.data.At import net.mamoe.mirai.message.MessageReceipt
import net.mamoe.mirai.message.data.MessageChainBuilder import net.mamoe.mirai.message.data.*
import net.mamoe.mirai.utils.info import net.mamoe.mirai.utils.info
object JCompilerCollection : KotlinPlugin( object JCompilerCollection : KotlinPlugin(
JvmPluginDescription( JvmPluginDescription(
id = "top.jie65535.mirai-console-jcc-plugin", id = "top.jie65535.mirai-console-jcc-plugin",
name = "J Compiler Collection", name = "J Compiler Collection",
version = "1.0", version = "1.1.0",
) { ) {
author("jie65535") author("jie65535")
info("""在线编译器集合""") info("""在线编译器集合""")
@@ -26,35 +29,53 @@ object JCompilerCollection : KotlinPlugin(
override fun onEnable() { override fun onEnable() {
logger.info { "Plugin loaded" } logger.info { "Plugin loaded" }
JccCommand.register() JccCommand.register()
JccPluginData.reload()
globalEventChannel()
.parentScope(this)
.subscribeMessages {
content {
message.firstIsInstanceOrNull<PlainText>()?.content?.trimStart()?.startsWith(CMD_PREFIX) == true
} reply {
val msg = message.firstIsInstance<PlainText>().content.trimStart().removePrefix(CMD_PREFIX).trim()
if (msg.isBlank()) {
return@reply "请输入正确的命令!例如:\n$CMD_PREFIX python print(\"Hello world\")"
}
globalEventChannel().subscribeMessages {
startsWith(CMD_PREFIX, false) reply {
if (subject is Group && (subject as Group).isBotMuted)
return@reply null
val msg = it.substring(CMD_PREFIX.length).trim()
if (msg.isNotEmpty()) {
val index = msg.indexOfFirst(Char::isWhitespace) val index = msg.indexOfFirst(Char::isWhitespace)
val language = if (index >= 0) msg.substring(0, index) else msg val language = if (index >= 0) msg.substring(0, index) else msg
if (!GlotAPI.checkSupport(language)) if (!GlotAPI.checkSupport(language))
return@reply "不支持这种编程语言\n/jcc list #列出所有支持的编程语言" return@reply "不支持这种编程语言\n/jcc list #列出所有支持的编程语言"
var code = if (index >= 0) {
try {
// 检查命令的引用
val quote = message[QuoteReply]
var input: String? = null
// 支持运行引用的消息的代码
var code = if (quote != null) {
// run c [input]
if (index >= 0) {
input = msg.substring(index).trim()
}
quote.source.originalMessage.content
} else if (index >= 0) {
msg.substring(index).trim() msg.substring(index).trim()
} else { } else {
return@reply "$CMD_PREFIX $language\n" + GlotAPI.getTemplateFile(language).content return@reply "$CMD_PREFIX $language\n" + GlotAPI.getTemplateFile(language).content
} }
try { // 如果是引用消息,则不再从原消息中分析。否则,还要从消息中判断是否存在输入参数
val si = code.indexOfFirst(Char::isWhitespace) val si = if (quote != null) 0 else code.indexOfFirst(Char::isWhitespace)
// 尝试得到url
val url = if (si > 0) { val url = if (si > 0) {
code.substring(0, si) code.substring(0, si)
} else { } else {
code code
} }
var input: String? = null // 如果参数是一个ubuntu pastebin的链接则去获取具体代码
// 如果参数是一个ubuntu pastebin的链接则去获取
if (UbuntuPastebinHelper.checkUrl(url)) { if (UbuntuPastebinHelper.checkUrl(url)) {
if (si > 0) { if (si > 0) {
// 如果确实是一个链接,则链接后面跟的内容就是输入内容
input = code.substring(si+1) input = code.substring(si+1)
} }
logger.info("$url 中获取代码") logger.info("$url 中获取代码")
@@ -106,8 +127,6 @@ object JCompilerCollection : KotlinPlugin(
return@reply "执行失败\n原因:${e.message}" return@reply "执行失败\n原因:${e.message}"
} }
} }
return@reply "请输入正确的命令!例如:\n$CMD_PREFIX python print(\"Hello world\")"
}
} }
} }

View File

@@ -21,12 +21,11 @@ object JccCommand : CompositeCommand(
@Description("帮助") @Description("帮助")
suspend fun CommandSender.help() { suspend fun CommandSender.help() {
sendMessage( sendMessage(
"$CMD_PREFIX <language> <code|pastebin> [stdin]\n" + "在线运行代码指令:\n" +
"例如:${CMD_PREFIX} python print(\"Hello world\")\n" + "$CMD_PREFIX <language> <code>\n" +
"支持从pastebin.ubuntu.com中运行代码\n" + "$CMD_PREFIX <language> <pastebinUrl> [stdin]\n" +
"$CMD_PREFIX c https://pastebin.ubuntu.com/p/KhBB7ZjVbD/\n" + "引用消息: $CMD_PREFIX <language> [stdin]\n" +
"你还可以在后面跟随标准输入仅pastebin支持\n" + "仓库地址https://github.com/jie65535/mirai-console-jcc-plugin\n" +
"$CMD_PREFIX c https://pastebin.ubuntu.com/p/S2PyvRqJNf/ 1 2 3 4\n" +
"其它指令:\n" + "其它指令:\n" +
usage usage
) )

View File

@@ -0,0 +1,15 @@
import net.mamoe.mirai.console.data.AutoSavePluginData
import net.mamoe.mirai.console.data.value
object JccPluginData: AutoSavePluginData("GlotCache") {
/**
* 支持的语言
*/
var languages: List<GlotAPI.Language> by value()
/**
* 模板文件
*/
val templateFiles: MutableMap<String, GlotAPI.CodeFile> by value()
}