diff --git a/README.md b/README.md index 384178b..3f3f7ec 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,17 @@ # J Grasscutter Command -# 在QQ群里远程执行命令的插件 + +This repo is only used for the Chinese social software QQ, so only the Chinese version is available. + +# 用QQ执行GC命令的机器人插件 - 基于 [Mirai-Console](https://github.com/mamoe/mirai-console) 开发的插件 -- 服务端必须使用 [OpenCommand](https://github.com/jie65535/gc-opencommand-plugin) 插件 +> Mirai机器人相关文档请参阅 [用户手册](https://github.com/mamoe/mirai/blob/dev/docs/UserManual.md), +> 本项目**不会教你**如何安装和登录机器人,请自行了解Mirai相关信息。_目前暂不考虑其它框架或平台,有意者可自行移植_ -Mirai机器人相关文档请参阅 [用户手册](https://github.com/mamoe/mirai/blob/dev/docs/UserManual.md), -本项目**不会教你**如何安装和登录机器人,请自行了解Mirai相关信息。 +- 服务端必须使用 [OpenCommand](https://github.com/jie65535/gc-opencommand-plugin) 插件 +- 若使用后觉得满意,可以给我一个 Star 作为鼓励 ; ) +- 若有问题或者建议,欢迎提出 Issue 进行反馈。 +- 建议 Watch 本项目以接收更新推送。 # 插件用法 @@ -83,6 +89,24 @@ _可以通过 `/jgc setBindCommand ` 来修改执行命令前缀 _(例 ![At群员示例图](screenshot/runAt.png) +--- + +你还可以一次性执行多条命令,并且可以通过在别名中设置多行命令来实现组合命令 + +例如: +```shell +!give 102 9999 +give 203 999 +``` +![多行命令示例图](screenshot/batch.jpg) + +还可以设置别名为多条命令,用`|`分隔,例如: + +`/jgc setCommand 新手礼包 give 102 9999|give 202 99|give 203 99` + +然后通过别名批量执行命令,例如:`!新手礼包` + + ## 私聊执行 v0.3.0 开始,玩家可以**私聊机器人**进行账号的绑定和命令的执行, 但是目前只能在**默认服务器**中执行,无法指定执行的服务器。 @@ -176,7 +200,8 @@ defaultServerId: 1 ## 命令相关 ```shell -/jgc setCommand # 添加命令别名 +/jgc listCommands # 列出所有别名 +/jgc setCommand # 添加命令别名(聊天执行可传多行命令) /jgc removeCommand # 删除命令别名 /jgc addPublicCommand # 添加公开命令(可用别名)(游客可用) /jgc removePublicCommand # 删除公开命令 diff --git a/screenshot/batch.jpg b/screenshot/batch.jpg new file mode 100644 index 0000000..656cd8c Binary files /dev/null and b/screenshot/batch.jpg differ diff --git a/src/main/kotlin/JGrasscutterCommand.kt b/src/main/kotlin/JGrasscutterCommand.kt index 7b65d6f..66313ad 100644 --- a/src/main/kotlin/JGrasscutterCommand.kt +++ b/src/main/kotlin/JGrasscutterCommand.kt @@ -111,16 +111,16 @@ object JGrasscutterCommand : KotlinPlugin( // 处理执行游戏命令 else if (message.startsWith(PluginConfig.commandPrefix)) { message = message.removePrefix(PluginConfig.commandPrefix).trim() - if (message.isEmpty() || (message[0] == '/' && message.length == 1)) { + if (message.isEmpty()) { return@subscribeAlways } // 检查是否使用别名 var command = PluginConfig.commandAlias[message] - if (command.isNullOrEmpty()) - command = message - // 如果是斜杠开头,则移除斜杠,在控制台执行不需要斜杠 - if (command[0] == '/') command = command.substring(1) + command = if (command.isNullOrEmpty()) + message + else + command.replace('|', '\n') // 若为多行命令,替换为换行 // 执行的用户 var user: User? = null @@ -153,12 +153,8 @@ object JGrasscutterCommand : KotlinPlugin( try { // 调用接口执行命令 - val response = OpenCommandApi.runCommand(server.address, token, command) - if (response.isNullOrEmpty()) { - subject.sendMessage(this.message.quote() + "OK") - } else { - subject.sendMessage(this.message.quote() + response) - } + val response = OpenCommandApi.runCommands(server.address, token, command) + subject.sendMessage(this.message.quote() + response) if (user != null) { // 计数并更新最后运行时间 ++user.runCount @@ -193,7 +189,7 @@ object JGrasscutterCommand : KotlinPlugin( // 否则如果启用了同步消息,且控制台令牌不为空,且为群消息时 else if (server.consoleToken.isNotEmpty() && server.syncMessage && this is GroupMessageEvent) { try { - OpenCommandApi.runCommand( + OpenCommandApi.runCommands( server.address, server.consoleToken, "say ${sender.nameCardOrNick}:\n${this.message.contentToString()}") diff --git a/src/main/kotlin/PluginCommands.kt b/src/main/kotlin/PluginCommands.kt index 937a9f2..ce7bf27 100644 --- a/src/main/kotlin/PluginCommands.kt +++ b/src/main/kotlin/PluginCommands.kt @@ -332,7 +332,13 @@ object PluginCommands : CompositeCommand( // region 命令别名部分 @SubCommand - @Description("添加命令别名") + @Description("列出所有别名") + suspend fun CommandSender.listCommands() { + sendMessage(PluginConfig.commandAlias.map { "[${it.key}] ${it.value}" }.joinToString()) + } + + @SubCommand + @Description("添加命令别名,多条命令用|隔开") suspend fun CommandSender.setCommand(alias: String, vararg command: String) { if (alias.isEmpty() || command.isEmpty() || command[0].isEmpty()) { sendMessage("参数不能为空") diff --git a/src/main/kotlin/opencommand/OpenCommandApi.kt b/src/main/kotlin/opencommand/OpenCommandApi.kt index dc26966..4650753 100644 --- a/src/main/kotlin/opencommand/OpenCommandApi.kt +++ b/src/main/kotlin/opencommand/OpenCommandApi.kt @@ -140,13 +140,47 @@ object OpenCommandApi { /** * 运行命令,成功时返回命令执行结果,失败时抛出异常,异常详情参考doRequest描述 + * 允许单次执行多条命令,用换行(\n)分隔 * @param host 服务器地址 * @param token 持久令牌 - * @param command 命令行 + * @param rawCommands 命令行 * @return 命令执行结果 * @see doRequest */ - suspend fun runCommand(host: String, token: String, command: String): String? { - return doRequest(host, json.encodeToString(CommandRequest(token, command))) + suspend fun runCommands(host: String, token: String, rawCommands: String): String { + // 去除首尾空白、命令前缀。使用api执行命令不需要前缀 + val commands = rawCommands.splitToSequence('\n') + .map { it.trim().trimStart('/').trimStart('!') } + .toList() + return if (commands.isEmpty()) + throw IllegalArgumentException("命令不能为空!") + else if (commands.size == 1) { + val ret = doRequest(host, json.encodeToString(CommandRequest(token, commands[0]))) + if (ret.isNullOrEmpty()) "OK" else ret + } else { + val msg = StringBuilder() + var okCount = 0 + for (cmd in commands) { + val ret = doRequest(host, json.encodeToString(CommandRequest(token, cmd))) + if (ret.isNullOrEmpty()) { + if (okCount++ == 0) + msg.append("OK") + } else { + if (okCount > 0) { + if (okCount > 1) { + msg.append('*').append(okCount) + } + msg.appendLine() + okCount = 0 + } + msg.appendLine(ret) + } + } + if (okCount > 1) // OK*n + msg.append('*').append(okCount) + else if (msg[msg.length-1] == '\n') // 移除额外的换行 + msg.deleteCharAt(msg.length-1) + msg.toString() + } } } \ No newline at end of file