mirror of
https://github.com/mamoe/mirai.git
synced 2025-02-13 20:02:57 +08:00
Public API stabilization
This commit is contained in:
parent
30e359c282
commit
0f5d46d017
@ -7,7 +7,7 @@ import net.mamoe.mirai.console.plugin.Config;
|
||||
import net.mamoe.mirai.console.plugin.ConfigSection;
|
||||
import net.mamoe.mirai.console.plugin.ConfigSectionFactory;
|
||||
import net.mamoe.mirai.console.plugin.PluginBase;
|
||||
import net.mamoe.mirai.console.utils.Utils;
|
||||
import net.mamoe.mirai.console.util.Utils;
|
||||
import net.mamoe.mirai.message.GroupMessage;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jsoup.Jsoup;
|
||||
|
@ -1,6 +1,6 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.4-M2"
|
||||
kotlin("plugin.serialization") version "1.4-M2"
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.serialization")
|
||||
id("java")
|
||||
}
|
||||
|
||||
@ -10,8 +10,6 @@ kotlin {
|
||||
languageSettings.useExperimentalAnnotation("kotlin.Experimental")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.RequiresOptIn")
|
||||
languageSettings.progressiveMode = true
|
||||
languageSettings.languageVersion = "1.4"
|
||||
languageSettings.apiVersion = "1.4"
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
|
||||
|
@ -6,11 +6,12 @@ import java.util.Date
|
||||
import java.util.TimeZone
|
||||
|
||||
plugins {
|
||||
kotlin("jvm") version Versions.kotlinCompiler
|
||||
kotlin("plugin.serialization") version Versions.kotlinCompiler
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.serialization")
|
||||
id("java")
|
||||
`maven-publish`
|
||||
id("com.jfrog.bintray")
|
||||
id("net.mamoe.kotlin-jvm-blocking-bridge")
|
||||
}
|
||||
|
||||
version = Versions.console
|
||||
@ -31,8 +32,9 @@ kotlin {
|
||||
sourceSets.all {
|
||||
target.compilations.all {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=enable"
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||
//useIR = true
|
||||
}
|
||||
}
|
||||
languageSettings.apply {
|
||||
@ -45,7 +47,7 @@ kotlin {
|
||||
useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI")
|
||||
useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI")
|
||||
useExperimentalAnnotation("net.mamoe.mirai.console.ConsoleFrontEndImplementation")
|
||||
useExperimentalAnnotation("net.mamoe.mirai.console.utils.ConsoleExperimentalAPI")
|
||||
useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalAPI")
|
||||
useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
||||
useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
|
||||
useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts")
|
||||
|
@ -1,189 +0,0 @@
|
||||
package net.mamoe.mirai.console.command;
|
||||
|
||||
import kotlin.NotImplementedError;
|
||||
import kotlin.coroutines.Continuation;
|
||||
import kotlin.coroutines.EmptyCoroutineContext;
|
||||
import kotlinx.coroutines.BuildersKt;
|
||||
import kotlinx.coroutines.CoroutineScope;
|
||||
import kotlinx.coroutines.CoroutineStart;
|
||||
import kotlinx.coroutines.future.FutureKt;
|
||||
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI;
|
||||
import net.mamoe.mirai.message.data.Message;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
/**
|
||||
* Java 适配的 {@link CommandManagerKt}
|
||||
*/
|
||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||
public final class JCommandManager {
|
||||
private JCommandManager() {
|
||||
throw new NotImplementedError();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指令前缀
|
||||
*
|
||||
* @return 指令前缀
|
||||
*/
|
||||
@NotNull
|
||||
public static String getCommandPrefix() {
|
||||
return CommandManagerKt.getCommandPrefix();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取一个指令所有者已经注册了的指令列表.
|
||||
*
|
||||
* @param owner 指令所有者
|
||||
* @return 指令列表
|
||||
*/
|
||||
@NotNull
|
||||
public static List<@NotNull Command> getRegisteredCommands(final @NotNull CommandOwner owner) {
|
||||
return CommandManagerKt.getRegisteredCommands(Objects.requireNonNull(owner, "owner"));
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个指令.
|
||||
*
|
||||
* @param command 指令实例
|
||||
* @param override 是否覆盖重名指令.
|
||||
* <p>
|
||||
* 若原有指令 P, 其 {@link Command#getNames()} 为 'a', 'b', 'c'. <br>
|
||||
* 新指令 Q, 其 {@link Command#getNames()} 为 'b', 将会覆盖原指令 A 注册的 'b'.
|
||||
* <p>
|
||||
* 即注册完成后, 'a' 和 'c' 将会解析到指令 P, 而 'b' 会解析到指令 Q.
|
||||
* @return 若已有重名指令, 且 <code>override</code> 为 <code>false</code>, 返回 <code>false</code>; <br>
|
||||
* 若已有重名指令, 但 <code>override</code> 为 <code>true</code>, 覆盖原有指令并返回 <code>true</code>.
|
||||
*/
|
||||
public static boolean register(final @NotNull Command command, final boolean override) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
return CommandManagerKt.register(command, override);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个指令, 已有重复名称的指令时返回 <code>false</code>
|
||||
*
|
||||
* @param command 指令实例
|
||||
* @return 若已有重名指令, 返回 <code>false</code>, 否则返回 <code>true</code>.
|
||||
*/
|
||||
public static boolean register(final @NotNull Command command) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
return register(command, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找并返回重名的指令. 返回重名指令.
|
||||
*/
|
||||
@Nullable
|
||||
public static Command findDuplicate(final @NotNull Command command) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
return CommandManagerKt.findDuplicate(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消注册这个指令. 若指令未注册, 返回 <code>false</code>.
|
||||
*/
|
||||
public static boolean unregister(final @NotNull Command command) {
|
||||
Objects.requireNonNull(command, "command");
|
||||
return CommandManagerKt.unregister(command);
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消注册所有属于 <code>owner</code> 的指令
|
||||
*
|
||||
* @param owner 指令所有者
|
||||
*/
|
||||
public static void unregisterAllCommands(final @NotNull CommandOwner owner) {
|
||||
Objects.requireNonNull(owner, "owner");
|
||||
CommandManagerKt.unregisterAllCommands(owner);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令
|
||||
*
|
||||
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 <code>null</code>
|
||||
* @throws CommandExecutionException 当 {@link Command#onCommand(CommandSender, Object[], Continuation)} 抛出异常时包装并附带相关指令信息抛出
|
||||
* @see #executeCommandAsync(CoroutineScope, CommandSender, Object...)
|
||||
*/
|
||||
@Nullable
|
||||
public static Command executeCommand(final @NotNull CommandSender sender, final @NotNull Object... args) throws CommandExecutionException, InterruptedException {
|
||||
Objects.requireNonNull(sender, "sender");
|
||||
Objects.requireNonNull(args, "args");
|
||||
for (Object arg : args) {
|
||||
Objects.requireNonNull(arg, "element of args");
|
||||
}
|
||||
|
||||
return BuildersKt.runBlocking(EmptyCoroutineContext.INSTANCE, (scope, completion) -> CommandManagerKt.executeCommand(sender, args, completion));
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步 (在 Kotlin 协程线程池) 解析并执行一个指令
|
||||
*
|
||||
* @param scope 协程作用域 (用于管理协程生命周期). 一般填入 {@link JavaPlugin} 实例.
|
||||
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 <code>null</code>
|
||||
* @see #executeCommand(CommandSender, Object...)
|
||||
*/
|
||||
@NotNull
|
||||
public static CompletableFuture<@Nullable Command> executeCommandAsync(final @NotNull CoroutineScope scope, final @NotNull CommandSender sender, final @NotNull Object... args) {
|
||||
Objects.requireNonNull(sender, "sender");
|
||||
Objects.requireNonNull(args, "args");
|
||||
Objects.requireNonNull(scope, "scope");
|
||||
for (Object arg : args) {
|
||||
Objects.requireNonNull(arg, "element of args");
|
||||
}
|
||||
|
||||
return FutureKt.future(scope, EmptyCoroutineContext.INSTANCE, CoroutineStart.DEFAULT, (sc, completion) -> CommandManagerKt.executeCommand(sender, args, completion));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令, 获取详细的指令参数等信息.
|
||||
* <br />
|
||||
* 执行过程中产生的异常将不会直接抛出, 而会包装为 {@link CommandExecuteResult.ExecutionException}
|
||||
*
|
||||
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||
* @return 执行结果
|
||||
* @see #executeCommandDetailedAsync(CoroutineScope, CommandSender, Object...)
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@NotNull
|
||||
public static CommandExecuteResult executeCommandDetailed(final @NotNull CommandSender sender, final @NotNull Object... args) throws InterruptedException {
|
||||
Objects.requireNonNull(sender, "sender");
|
||||
Objects.requireNonNull(args, "args");
|
||||
for (Object arg : args) {
|
||||
Objects.requireNonNull(arg, "element of args");
|
||||
}
|
||||
|
||||
return BuildersKt.runBlocking(EmptyCoroutineContext.INSTANCE, (scope, completion) -> CommandManagerKt.executeCommandDetailed(sender, args, completion));
|
||||
}
|
||||
|
||||
/**
|
||||
* 异步 (在 Kotlin 协程线程池) 解析并执行一个指令, 获取详细的指令参数等信息
|
||||
*
|
||||
* @param scope 协程作用域 (用于管理协程生命周期). 一般填入 {@link JavaPlugin} 实例.
|
||||
* @param args 接受 {@link String} 或 {@link Message} , 其他对象将会被 {@link Object#toString()}
|
||||
* @return 执行结果
|
||||
* @see #executeCommandDetailed(CommandSender, Object...)
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@NotNull
|
||||
public static CompletableFuture<@NotNull CommandExecuteResult>
|
||||
executeCommandDetailedAsync(final @NotNull CoroutineScope scope, final @NotNull CommandSender sender, final @NotNull Object... args) {
|
||||
Objects.requireNonNull(sender, "sender");
|
||||
Objects.requireNonNull(args, "args");
|
||||
Objects.requireNonNull(scope, "scope");
|
||||
for (Object arg : args) {
|
||||
Objects.requireNonNull(arg, "element of args");
|
||||
}
|
||||
|
||||
return FutureKt.future(scope, EmptyCoroutineContext.INSTANCE, CoroutineStart.DEFAULT, (sc, completion) -> CommandManagerKt.executeCommandDetailed(sender, args, completion));
|
||||
}
|
||||
}
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.utils;
|
||||
|
||||
import net.mamoe.mirai.Bot;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 获取 Bot Manager
|
||||
* Java 友好 API
|
||||
*/
|
||||
public class BotManager {
|
||||
|
||||
public static List<Long> getManagers(long botAccount) {
|
||||
Bot bot = Bot.getInstance(botAccount);
|
||||
return getManagers(bot);
|
||||
}
|
||||
|
||||
public static List<Long> getManagers(Bot bot) {
|
||||
return BotManagers.getManagers(bot);
|
||||
}
|
||||
|
||||
public static boolean isManager(Bot bot, long target) {
|
||||
return getManagers(bot).contains(target);
|
||||
}
|
||||
|
||||
public static boolean isManager(long botAccount, long target) {
|
||||
return getManagers(botAccount).contains(target);
|
||||
}
|
||||
}
|
||||
|
@ -14,38 +14,23 @@ package net.mamoe.mirai.console
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.io.charsets.Charset
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsole.INSTANCE
|
||||
import net.mamoe.mirai.console.command.BuiltInCommands
|
||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||
import net.mamoe.mirai.console.command.internal.InternalCommandManager
|
||||
import net.mamoe.mirai.console.command.primaryName
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.PluginManager
|
||||
import net.mamoe.mirai.console.plugin.center.CuiPluginCenter
|
||||
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.PluginManagerImpl
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.utils.ConsoleBuiltInSettingStorage
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.utils.DefaultLogger
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.info
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
|
||||
/**
|
||||
* mirai-console 实例
|
||||
*
|
||||
* @see INSTANCE
|
||||
* @see MiraiConsoleImplementation
|
||||
*/
|
||||
public interface MiraiConsole : CoroutineScope {
|
||||
/**
|
||||
@ -56,6 +41,7 @@ public interface MiraiConsole : CoroutineScope {
|
||||
/**
|
||||
* Console 前端接口
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public val frontEnd: MiraiConsoleFrontEnd
|
||||
|
||||
/**
|
||||
@ -74,6 +60,7 @@ public interface MiraiConsole : CoroutineScope {
|
||||
|
||||
public val version: String
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
public val pluginCenter: PluginCenter
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
@ -94,80 +81,3 @@ public class IllegalMiraiConsoleImplementationError @JvmOverloads constructor(
|
||||
public override val cause: Throwable? = null
|
||||
) : Error()
|
||||
|
||||
|
||||
internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants)
|
||||
@JvmStatic
|
||||
val buildDate: Date = Date(1595136353901L) // 2020-07-19 13:25:53
|
||||
const val version: String = "1.0-dev-4"
|
||||
}
|
||||
|
||||
/**
|
||||
* [MiraiConsole] 公开 API 与前端实现的连接桥.
|
||||
*/
|
||||
internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleImplementation,
|
||||
MiraiConsole {
|
||||
override val pluginCenter: PluginCenter get() = CuiPluginCenter
|
||||
|
||||
private val instance: MiraiConsoleImplementation get() = MiraiConsoleImplementation.instance
|
||||
override val buildDate: Date get() = MiraiConsoleBuildConstants.buildDate
|
||||
override val version: String get() = MiraiConsoleBuildConstants.version
|
||||
override val rootDir: File get() = instance.rootDir
|
||||
override val frontEnd: MiraiConsoleFrontEnd get() = instance.frontEnd
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
override val mainLogger: MiraiLogger
|
||||
get() = instance.mainLogger
|
||||
override val coroutineContext: CoroutineContext get() = instance.coroutineContext
|
||||
override val builtInPluginLoaders: List<PluginLoader<*, *>> get() = instance.builtInPluginLoaders
|
||||
override val consoleCommandSender: ConsoleCommandSender get() = instance.consoleCommandSender
|
||||
|
||||
override val settingStorageForJarPluginLoader: SettingStorage get() = instance.settingStorageForJarPluginLoader
|
||||
override val settingStorageForBuiltIns: SettingStorage get() = instance.settingStorageForBuiltIns
|
||||
|
||||
init {
|
||||
DefaultLogger = { identity -> this.newLogger(identity) }
|
||||
}
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
override fun newLogger(identity: String?): MiraiLogger = frontEnd.loggerFor(identity)
|
||||
|
||||
internal fun doStart() {
|
||||
val buildDateFormatted = SimpleDateFormat("yyyy-MM-dd").format(buildDate)
|
||||
mainLogger.info { "Starting mirai-console..." }
|
||||
mainLogger.info { "Backend: version $version, built on $buildDateFormatted." }
|
||||
mainLogger.info { "Frontend ${frontEnd.name}: version $version." }
|
||||
|
||||
if (coroutineContext[Job] == null) {
|
||||
throw IllegalMiraiConsoleImplementationError("The coroutineContext given to MiraiConsole must have a Job in it.")
|
||||
}
|
||||
MiraiConsole.job.invokeOnCompletion {
|
||||
Bot.botInstances.forEach { kotlin.runCatching { it.close() }.exceptionOrNull()?.let(mainLogger::error) }
|
||||
}
|
||||
|
||||
BuiltInCommands.registerAll()
|
||||
mainLogger.info { "Preparing built-in commands: ${BuiltInCommands.all.joinToString { it.primaryName }}" }
|
||||
InternalCommandManager.commandListener // start
|
||||
|
||||
mainLogger.info { "Loading plugins..." }
|
||||
PluginManagerImpl.loadEnablePlugins()
|
||||
mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." }
|
||||
mainLogger.info { "mirai-console started successfully." }
|
||||
|
||||
ConsoleBuiltInSettingStorage // init
|
||||
// Only for initialize
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Included in kotlin stdlib 1.4
|
||||
*/
|
||||
internal val Throwable.stacktraceString: String
|
||||
get() =
|
||||
ByteArrayOutputStream().apply {
|
||||
printStackTrace(PrintStream(this))
|
||||
}.use { it.toByteArray().encodeToString() }
|
||||
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
internal inline fun ByteArray.encodeToString(charset: Charset = Charsets.UTF_8): String =
|
||||
kotlinx.io.core.String(this, charset = charset)
|
||||
|
@ -10,7 +10,7 @@
|
||||
package net.mamoe.mirai.console
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.utils.LoginSolver
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
|
||||
|
@ -13,10 +13,13 @@ package net.mamoe.mirai.console
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
|
||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
@ -35,7 +38,9 @@ import kotlin.annotation.AnnotationTarget.*
|
||||
public annotation class ConsoleFrontEndImplementation
|
||||
|
||||
/**
|
||||
* [MiraiConsole] 前端实现, 需低啊用
|
||||
* 由前端实现这个接口
|
||||
*
|
||||
* @see MiraiConsoleImplementation.start
|
||||
*/
|
||||
@ConsoleFrontEndImplementation
|
||||
public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
@ -47,6 +52,7 @@ public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
/**
|
||||
* Console 前端接口
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public val frontEnd: MiraiConsoleFrontEnd
|
||||
|
||||
/**
|
||||
@ -70,8 +76,9 @@ public interface MiraiConsoleImplementation : CoroutineScope {
|
||||
internal lateinit var instance: MiraiConsoleImplementation
|
||||
private val initLock = ReentrantLock()
|
||||
|
||||
/** 由前端调用, 初始化 [MiraiConsole] 实例, 并 */
|
||||
/** 由前端调用, 初始化 [MiraiConsole] 实例, 并启动 */
|
||||
@JvmStatic
|
||||
@ConsoleFrontEndImplementation
|
||||
public fun MiraiConsoleImplementation.start(): Unit = initLock.withLock {
|
||||
this@Companion.instance = this
|
||||
MiraiConsoleImplementationBridge.doStart()
|
||||
|
@ -16,7 +16,9 @@ import kotlinx.coroutines.sync.withLock
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.alsoLogin
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.stacktraceString
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
import net.mamoe.mirai.console.command.CommandManagerImpl.allRegisteredCommands
|
||||
import net.mamoe.mirai.console.command.CommandManagerImpl.register
|
||||
import net.mamoe.mirai.event.selectMessagesUnit
|
||||
import net.mamoe.mirai.utils.DirectoryLogger
|
||||
import net.mamoe.mirai.utils.weeksToMillis
|
||||
@ -138,7 +140,7 @@ public object BuiltInCommands {
|
||||
if (this is MessageEventContextAware<*>) {
|
||||
this.fromEvent.selectMessagesUnit {
|
||||
"stacktrace" reply {
|
||||
throwable.stacktraceString
|
||||
throwable.stackTraceToString()
|
||||
}
|
||||
}
|
||||
"test"
|
||||
|
@ -11,16 +11,20 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.internal.isValidSubName
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.execute
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.internal.command.isValidSubName
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
|
||||
/**
|
||||
* 指令
|
||||
* 通常情况下, 你的指令应继承 @see CompositeCommand/SimpleCommand
|
||||
* @see register 注册这个指令
|
||||
*
|
||||
* @see CommandManager.register 注册这个指令
|
||||
*
|
||||
* @see RawCommand
|
||||
* @see CompositeCommand
|
||||
* @see SimpleCommand
|
||||
*/
|
||||
public interface Command {
|
||||
/**
|
||||
@ -28,8 +32,14 @@ public interface Command {
|
||||
*/
|
||||
public val names: Array<out String>
|
||||
|
||||
/**
|
||||
* 用法说明, 用于发送给用户
|
||||
*/
|
||||
public val usage: String
|
||||
|
||||
/**
|
||||
* 指令描述, 用于显示在 [BuiltInCommands.Help]
|
||||
*/
|
||||
public val description: String
|
||||
|
||||
/**
|
||||
@ -38,20 +48,37 @@ public interface Command {
|
||||
public val permission: CommandPermission
|
||||
|
||||
/**
|
||||
* 为 `true` 时表示 [指令前缀][CommandPrefix] 可选
|
||||
* 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选
|
||||
*/
|
||||
public val prefixOptional: Boolean
|
||||
|
||||
/**
|
||||
* 指令拥有者, 对于插件的指令通常是 [PluginCommandOwner]
|
||||
*/
|
||||
public val owner: CommandOwner
|
||||
|
||||
/**
|
||||
* @param args 指令参数. 可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割.
|
||||
* @param args 指令参数. 数组元素类型可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割.
|
||||
*
|
||||
* @see Command.execute
|
||||
*/ // TODO: 2020/6/28 Java-friendly bridges
|
||||
* @see CommandManager.execute
|
||||
*/
|
||||
@JvmBlockingBridge
|
||||
public suspend fun CommandSender.onCommand(args: Array<out Any>)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* 主要指令名. 为 [Command.names] 的第一个元素.
|
||||
*/
|
||||
@JvmStatic
|
||||
public val Command.primaryName: String
|
||||
get() = names[0]
|
||||
}
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
public suspend inline fun Command.onCommand(sender: CommandSender, args: Array<out Any>): Unit =
|
||||
sender.run { onCommand(args) }
|
||||
|
||||
/**
|
||||
* [Command] 的基础实现
|
||||
*/
|
||||
@ -68,12 +95,4 @@ public abstract class AbstractCommand @JvmOverloads constructor(
|
||||
list.firstOrNull { !it.isValidSubName() }?.let { error("Invalid name: $it") }
|
||||
}.toTypedArray()
|
||||
|
||||
}
|
||||
|
||||
public suspend inline fun Command.onCommand(sender: CommandSender, args: Array<out Any>): Unit =
|
||||
sender.run { onCommand(args) }
|
||||
|
||||
/**
|
||||
* 主要指令名. 为 [Command.names] 的第一个元素.
|
||||
*/
|
||||
public val Command.primaryName: String get() = names[0]
|
||||
}
|
@ -11,6 +11,8 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
|
||||
/**
|
||||
* 在 [executeCommand] 中, [Command.onCommand] 抛出异常时包装的异常.
|
||||
*/
|
||||
|
@ -15,15 +15,163 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.console.command.internal.*
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.console.command.CommandManagerImpl.unregisterAllCommands
|
||||
import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
|
||||
public interface CommandManager {
|
||||
/**
|
||||
* 获取已经注册了的属于这个 [CommandOwner] 的指令列表.
|
||||
*/
|
||||
public val CommandOwner.registeredCommands: List<Command>
|
||||
|
||||
/**
|
||||
* 获取所有已经注册了指令列表.
|
||||
*/
|
||||
public val allRegisteredCommands: List<Command>
|
||||
|
||||
/**
|
||||
* 指令前缀, 如 '/'
|
||||
*/
|
||||
public val commandPrefix: String
|
||||
|
||||
/**
|
||||
* 取消注册所有属于 [this] 的指令
|
||||
*/
|
||||
public fun CommandOwner.unregisterAllCommands()
|
||||
|
||||
/**
|
||||
* 注册一个指令.
|
||||
*
|
||||
* @param override 是否覆盖重名指令.
|
||||
*
|
||||
* 若原有指令 P, 其 [Command.names] 为 'a', 'b', 'c'.
|
||||
* 新指令 Q, 其 [Command.names] 为 'b', 将会覆盖原指令 A 注册的 'b'.
|
||||
*
|
||||
* 即注册完成后, 'a' 和 'c' 将会解析到指令 P, 而 'b' 会解析到指令 Q.
|
||||
*
|
||||
* @return
|
||||
* 若已有重名指令, 且 [override] 为 `false`, 返回 `false`;
|
||||
* 若已有重名指令, 但 [override] 为 `true`, 覆盖原有指令并返回 `true`.
|
||||
*/
|
||||
public fun Command.register(override: Boolean = false): Boolean
|
||||
|
||||
/**
|
||||
* 查找并返回重名的指令. 返回重名指令.
|
||||
*/
|
||||
public fun Command.findDuplicate(): Command?
|
||||
|
||||
/**
|
||||
* 取消注册这个指令. 若指令未注册, 返回 `false`.
|
||||
*/
|
||||
public fun Command.unregister(): Boolean
|
||||
|
||||
/**
|
||||
* 当 [this] 已经 [注册][register] 后返回 `true`
|
||||
*/
|
||||
public fun Command.isRegistered(): Boolean
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令. 将会检查指令权限, 在无权限时抛出
|
||||
*
|
||||
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*/
|
||||
@JvmBlockingBridge
|
||||
public suspend fun CommandSender.executeCommand(vararg messages: Any): Command?
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*/
|
||||
@Throws(CommandExecutionException::class)
|
||||
@JvmBlockingBridge
|
||||
public suspend fun CommandSender.executeCommand(message: MessageChain): Command?
|
||||
|
||||
/**
|
||||
* 执行一个指令
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*/
|
||||
@JvmBlockingBridge
|
||||
@Throws(CommandExecutionException::class)
|
||||
public suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean = true)
|
||||
|
||||
/**
|
||||
* 执行一个指令
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*/
|
||||
@JvmBlockingBridge
|
||||
@Throws(CommandExecutionException::class)
|
||||
public suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean = true)
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令, 获取详细的指令参数等信息
|
||||
*
|
||||
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
||||
*
|
||||
* @return 执行结果
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@JvmBlockingBridge
|
||||
public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令, 获取详细的指令参数等信息
|
||||
*
|
||||
* 执行过程中产生的异常将不会直接抛出, 而会包装为 [CommandExecuteResult.ExecutionException]
|
||||
*
|
||||
* @return 执行结果
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@JvmBlockingBridge
|
||||
public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult
|
||||
|
||||
public companion object INSTANCE : CommandManager by CommandManagerImpl {
|
||||
override val CommandOwner.registeredCommands: List<Command> get() = CommandManagerImpl.run { registeredCommands }
|
||||
override fun CommandOwner.unregisterAllCommands(): Unit = CommandManagerImpl.run { unregisterAllCommands() }
|
||||
override fun Command.register(override: Boolean): Boolean = CommandManagerImpl.run { register(override) }
|
||||
override fun Command.findDuplicate(): Command? = CommandManagerImpl.run { findDuplicate() }
|
||||
override fun Command.unregister(): Boolean = CommandManagerImpl.run { unregister() }
|
||||
override fun Command.isRegistered(): Boolean = CommandManagerImpl.run { isRegistered() }
|
||||
override suspend fun CommandSender.executeCommand(vararg messages: Any): Command? =
|
||||
CommandManagerImpl.run { executeCommand(*messages) }
|
||||
|
||||
override suspend fun CommandSender.executeCommand(message: MessageChain): Command? =
|
||||
CommandManagerImpl.run { executeCommand(message) }
|
||||
|
||||
override suspend fun Command.execute(
|
||||
sender: CommandSender,
|
||||
args: MessageChain,
|
||||
checkPermission: Boolean
|
||||
): Unit =
|
||||
CommandManagerImpl.run { execute(sender, args = args, checkPermission = checkPermission) }
|
||||
|
||||
override suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean): Unit =
|
||||
CommandManagerImpl.run { execute(sender, args = args, checkPermission = checkPermission) }
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
override suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult =
|
||||
CommandManagerImpl.run { executeCommandDetailed(*messages) }
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
override suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult =
|
||||
CommandManagerImpl.run { executeCommandDetailed(messages) }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 指令的所有者.
|
||||
* @see PluginCommandOwner
|
||||
@ -33,7 +181,9 @@ public sealed class CommandOwner
|
||||
/**
|
||||
* 插件指令所有者. 插件只能通过 [PluginCommandOwner] 管理指令.
|
||||
*/
|
||||
public abstract class PluginCommandOwner(public val plugin: Plugin) : CommandOwner() {
|
||||
public abstract class PluginCommandOwner(
|
||||
public val plugin: Plugin
|
||||
) : CommandOwner() {
|
||||
init {
|
||||
if (plugin is CoroutineScope) { // JVM Plugin
|
||||
plugin.coroutineContext[Job]?.invokeOnCompletion {
|
||||
@ -47,239 +197,3 @@ public abstract class PluginCommandOwner(public val plugin: Plugin) : CommandOwn
|
||||
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
|
||||
*/
|
||||
public object ConsoleCommandOwner : CommandOwner()
|
||||
|
||||
/**
|
||||
* 获取已经注册了的属于这个 [CommandOwner] 的指令列表.
|
||||
* @see JCommandManager.getRegisteredCommands Java 方法
|
||||
*/
|
||||
public val CommandOwner.registeredCommands: List<Command> get() = InternalCommandManager.registeredCommands.filter { it.owner == this }
|
||||
|
||||
/**
|
||||
* 获取所有已经注册了指令列表.
|
||||
* @see JCommandManager.getRegisteredCommands Java 方法
|
||||
*/
|
||||
public val allRegisteredCommands: List<Command> get() = InternalCommandManager.registeredCommands.toList() // copy
|
||||
|
||||
/**
|
||||
* 指令前缀, 如 '/'
|
||||
* @see JCommandManager.getCommandPrefix Java 方法
|
||||
*/
|
||||
@get:JvmName("getCommandPrefix")
|
||||
public val CommandPrefix: String
|
||||
get() = InternalCommandManager.COMMAND_PREFIX
|
||||
|
||||
/**
|
||||
* 取消注册所有属于 [this] 的指令
|
||||
* @see JCommandManager.unregisterAllCommands Java 方法
|
||||
*/
|
||||
public fun CommandOwner.unregisterAllCommands() {
|
||||
for (registeredCommand in registeredCommands) {
|
||||
registeredCommand.unregister()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注册一个指令.
|
||||
*
|
||||
* @param override 是否覆盖重名指令.
|
||||
*
|
||||
* 若原有指令 P, 其 [Command.names] 为 'a', 'b', 'c'.
|
||||
* 新指令 Q, 其 [Command.names] 为 'b', 将会覆盖原指令 A 注册的 'b'.
|
||||
*
|
||||
* 即注册完成后, 'a' 和 'c' 将会解析到指令 P, 而 'b' 会解析到指令 Q.
|
||||
*
|
||||
* @return
|
||||
* 若已有重名指令, 且 [override] 为 `false`, 返回 `false`;
|
||||
* 若已有重名指令, 但 [override] 为 `true`, 覆盖原有指令并返回 `true`.
|
||||
*
|
||||
* @see JCommandManager.register Java 方法
|
||||
*/
|
||||
@JvmOverloads
|
||||
public fun Command.register(override: Boolean = false): Boolean {
|
||||
if (this is CompositeCommand) this.subCommands // init
|
||||
|
||||
InternalCommandManager.modifyLock.withLock {
|
||||
if (!override) {
|
||||
if (findDuplicate() != null) return false
|
||||
}
|
||||
InternalCommandManager.registeredCommands.add(this@register)
|
||||
if (this.prefixOptional) {
|
||||
for (name in this.names) {
|
||||
val lowerCaseName = name.toLowerCase()
|
||||
InternalCommandManager.optionalPrefixCommandMap[lowerCaseName] = this
|
||||
InternalCommandManager.requiredPrefixCommandMap[lowerCaseName] = this
|
||||
}
|
||||
} else {
|
||||
for (name in this.names) {
|
||||
val lowerCaseName = name.toLowerCase()
|
||||
InternalCommandManager.optionalPrefixCommandMap.remove(lowerCaseName) // ensure resolution consistency
|
||||
InternalCommandManager.requiredPrefixCommandMap[lowerCaseName] = this
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 查找并返回重名的指令. 返回重名指令.
|
||||
*
|
||||
* @see JCommandManager.findDuplicate Java 方法
|
||||
*/
|
||||
public fun Command.findDuplicate(): Command? =
|
||||
InternalCommandManager.registeredCommands.firstOrNull { it.names intersectsIgnoringCase this.names }
|
||||
|
||||
/**
|
||||
* 取消注册这个指令. 若指令未注册, 返回 `false`.
|
||||
*
|
||||
* @see JCommandManager.unregister Java 方法
|
||||
*/
|
||||
public fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock {
|
||||
if (this.prefixOptional) {
|
||||
this.names.forEach {
|
||||
InternalCommandManager.optionalPrefixCommandMap.remove(it)
|
||||
}
|
||||
}
|
||||
this.names.forEach {
|
||||
InternalCommandManager.requiredPrefixCommandMap.remove(it)
|
||||
}
|
||||
InternalCommandManager.registeredCommands.remove(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* 当 [this] 已经 [注册][register] 后返回 `true`
|
||||
*/
|
||||
public fun Command.isRegistered(): Boolean = this in InternalCommandManager.registeredCommands
|
||||
|
||||
//// executing without detailed result (faster)
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令. 将会检查指令权限, 在无权限时抛出
|
||||
*
|
||||
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*
|
||||
* @see JCommandManager.executeCommand Java 方法
|
||||
*/
|
||||
public suspend fun CommandSender.executeCommand(vararg messages: Any): Command? {
|
||||
if (messages.isEmpty()) return null
|
||||
return matchAndExecuteCommandInternal(messages, messages[0].toString().substringBefore(' '))
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*
|
||||
* @see JCommandManager.executeCommand Java 方法
|
||||
*/
|
||||
@Throws(CommandExecutionException::class)
|
||||
public suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
||||
if (message.isEmpty()) return null
|
||||
return matchAndExecuteCommandInternal(message, message[0].toString().substringBefore(' '))
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行一个指令
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*
|
||||
* @see JCommandManager.executeCommand Java 方法
|
||||
*/
|
||||
@JvmOverloads
|
||||
@Throws(CommandExecutionException::class)
|
||||
public suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean = true) {
|
||||
sender.executeCommandInternal(
|
||||
this,
|
||||
args.flattenCommandComponents().toTypedArray(),
|
||||
this.primaryName,
|
||||
checkPermission
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行一个指令
|
||||
*
|
||||
* @return 成功执行的指令, 在无匹配指令时返回 `null`
|
||||
* @throws CommandExecutionException 当 [Command.onCommand] 抛出异常时包装并附带相关指令信息抛出
|
||||
*
|
||||
* @see JCommandManager.executeCommand Java 方法
|
||||
*/
|
||||
@JvmOverloads
|
||||
@Throws(CommandExecutionException::class)
|
||||
public suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean = true) {
|
||||
sender.executeCommandInternal(
|
||||
this,
|
||||
args.flattenCommandComponents().toTypedArray(),
|
||||
this.primaryName,
|
||||
checkPermission
|
||||
)
|
||||
}
|
||||
|
||||
//// execution with detailed result
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令, 获取详细的指令参数等信息
|
||||
*
|
||||
* @param messages 接受 [String] 或 [Message], 其他对象将会被 [Any.toString]
|
||||
*
|
||||
* @return 执行结果
|
||||
*
|
||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析并执行一个指令, 获取详细的指令参数等信息
|
||||
*
|
||||
* 执行过程中产生的异常将不会直接抛出, 而会包装为 [CommandExecuteResult.ExecutionException]
|
||||
*
|
||||
* @return 执行结果
|
||||
*
|
||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||
return executeCommandDetailedInternal(messages, messages[0].toString())
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
internal suspend inline fun CommandSender.executeCommandDetailedInternal(
|
||||
messages: Any,
|
||||
commandName: String
|
||||
): CommandExecuteResult {
|
||||
val command =
|
||||
InternalCommandManager.matchCommand(commandName) ?: return CommandExecuteResult.CommandNotFound(commandName)
|
||||
val args = messages.flattenCommandComponents().dropToTypedArray(1)
|
||||
|
||||
if (!command.testPermission(this)) {
|
||||
return CommandExecuteResult.PermissionDenied(command, commandName)
|
||||
}
|
||||
kotlin.runCatching {
|
||||
command.onCommand(this, args)
|
||||
}.fold(
|
||||
onSuccess = {
|
||||
return CommandExecuteResult.Success(
|
||||
commandName = commandName,
|
||||
command = command,
|
||||
args = args
|
||||
)
|
||||
},
|
||||
onFailure = {
|
||||
return CommandExecuteResult.ExecutionException(
|
||||
commandName = commandName,
|
||||
command = command,
|
||||
exception = it,
|
||||
args = args
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -0,0 +1,156 @@
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
import net.mamoe.mirai.console.internal.command.*
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.event.Listener
|
||||
import net.mamoe.mirai.event.subscribeAlways
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import net.mamoe.mirai.message.data.MessageChain
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
internal object CommandManagerImpl : CommandManager, CoroutineScope by CoroutineScope(MiraiConsole.job) {
|
||||
@JvmField
|
||||
internal val registeredCommands: MutableList<Command> = mutableListOf()
|
||||
|
||||
/**
|
||||
* 全部注册的指令
|
||||
* /mute -> MuteCommand
|
||||
* /jinyan -> MuteCommand
|
||||
*/
|
||||
@JvmField
|
||||
internal val requiredPrefixCommandMap: MutableMap<String, Command> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* Command name of commands that are prefix optional
|
||||
* mute -> MuteCommand
|
||||
*/
|
||||
@JvmField
|
||||
internal val optionalPrefixCommandMap: MutableMap<String, Command> = mutableMapOf()
|
||||
|
||||
@JvmField
|
||||
internal val modifyLock = ReentrantLock()
|
||||
|
||||
|
||||
/**
|
||||
* 从原始的 command 中解析出 Command 对象
|
||||
*/
|
||||
internal fun matchCommand(rawCommand: String): Command? {
|
||||
if (rawCommand.startsWith(commandPrefix)) {
|
||||
return requiredPrefixCommandMap[rawCommand.substringAfter(commandPrefix).toLowerCase()]
|
||||
}
|
||||
return optionalPrefixCommandMap[rawCommand.toLowerCase()]
|
||||
}
|
||||
|
||||
internal val commandListener: Listener<MessageEvent> by lazy {
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
subscribeAlways<MessageEvent>(
|
||||
concurrency = Listener.ConcurrencyKind.CONCURRENT,
|
||||
priority = Listener.EventPriority.HIGH
|
||||
) {
|
||||
if (this.sender.asCommandSender().executeCommand(message) != null) {
|
||||
intercept()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///// IMPL
|
||||
|
||||
|
||||
override val CommandOwner.registeredCommands: List<Command> get() = registeredCommands.filter { it.owner == this }
|
||||
override val allRegisteredCommands: List<Command> get() = registeredCommands.toList() // copy
|
||||
override val commandPrefix: String get() = "/"
|
||||
override fun CommandOwner.unregisterAllCommands() {
|
||||
for (registeredCommand in registeredCommands) {
|
||||
registeredCommand.unregister()
|
||||
}
|
||||
}
|
||||
|
||||
override fun Command.register(override: Boolean): Boolean {
|
||||
if (this is CompositeCommand) this.subCommands // init
|
||||
|
||||
modifyLock.withLock {
|
||||
if (!override) {
|
||||
if (findDuplicate() != null) return false
|
||||
}
|
||||
registeredCommands.add(this@register)
|
||||
if (this.prefixOptional) {
|
||||
for (name in this.names) {
|
||||
val lowerCaseName = name.toLowerCase()
|
||||
optionalPrefixCommandMap[lowerCaseName] = this
|
||||
requiredPrefixCommandMap[lowerCaseName] = this
|
||||
}
|
||||
} else {
|
||||
for (name in this.names) {
|
||||
val lowerCaseName = name.toLowerCase()
|
||||
optionalPrefixCommandMap.remove(lowerCaseName) // ensure resolution consistency
|
||||
requiredPrefixCommandMap[lowerCaseName] = this
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
override fun Command.findDuplicate(): Command? =
|
||||
registeredCommands.firstOrNull { it.names intersectsIgnoringCase this.names }
|
||||
|
||||
override fun Command.unregister(): Boolean = modifyLock.withLock {
|
||||
if (this.prefixOptional) {
|
||||
this.names.forEach {
|
||||
optionalPrefixCommandMap.remove(it)
|
||||
}
|
||||
}
|
||||
this.names.forEach {
|
||||
requiredPrefixCommandMap.remove(it)
|
||||
}
|
||||
registeredCommands.remove(this)
|
||||
}
|
||||
|
||||
override fun Command.isRegistered(): Boolean = this in registeredCommands
|
||||
|
||||
//// executing without detailed result (faster)
|
||||
override suspend fun CommandSender.executeCommand(vararg messages: Any): Command? {
|
||||
if (messages.isEmpty()) return null
|
||||
return matchAndExecuteCommandInternal(messages, messages[0].toString().substringBefore(' '))
|
||||
}
|
||||
|
||||
override suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
||||
if (message.isEmpty()) return null
|
||||
return matchAndExecuteCommandInternal(message, message[0].toString().substringBefore(' '))
|
||||
}
|
||||
|
||||
override suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean) {
|
||||
sender.executeCommandInternal(
|
||||
this,
|
||||
args.flattenCommandComponents().toTypedArray(),
|
||||
this.primaryName,
|
||||
checkPermission
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean) {
|
||||
sender.executeCommandInternal(
|
||||
this,
|
||||
args.flattenCommandComponents().toTypedArray(),
|
||||
this.primaryName,
|
||||
checkPermission
|
||||
)
|
||||
}
|
||||
|
||||
//// execution with detailed result
|
||||
@ConsoleExperimentalAPI
|
||||
override suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
||||
}
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
override suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||
return executeCommandDetailedInternal(messages, messages[0].toString())
|
||||
}
|
||||
}
|
@ -12,7 +12,7 @@
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.utils.isManager
|
||||
import net.mamoe.mirai.console.util.BotManager.INSTANCE.isManager
|
||||
import net.mamoe.mirai.contact.isAdministrator
|
||||
import net.mamoe.mirai.contact.isOperator
|
||||
import net.mamoe.mirai.contact.isOwner
|
||||
@ -35,13 +35,11 @@ public interface CommandPermission {
|
||||
/**
|
||||
* 满足两个权限其中一个即可使用指令
|
||||
*/ // no extension for Java
|
||||
@JvmDefault
|
||||
public infix fun or(another: CommandPermission): CommandPermission = OrCommandPermission(this, another)
|
||||
|
||||
/**
|
||||
* 同时拥有两个权限才能使用指令
|
||||
*/ // no extension for Java
|
||||
@JvmDefault
|
||||
public infix fun and(another: CommandPermission): CommandPermission = AndCommandPermission(this, another)
|
||||
|
||||
|
||||
|
@ -9,6 +9,8 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
|
||||
/**
|
||||
* 在 [executeCommand] 中, [CommandSender] 未拥有 [Command.permission] 所要求的权限时抛出的异常.
|
||||
*
|
||||
|
@ -11,11 +11,10 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.kjbb.JvmBlockingBridge
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.utils.JavaFriendlyAPI
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.contact.*
|
||||
import net.mamoe.mirai.message.*
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
@ -38,17 +37,8 @@ public interface CommandSender {
|
||||
* 立刻发送一条消息
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@JvmBlockingBridge
|
||||
public suspend fun sendMessage(message: Message)
|
||||
|
||||
@JvmDefault
|
||||
@JavaFriendlyAPI
|
||||
@JvmName("sendMessage")
|
||||
public fun __sendMessageBlocking(messageChain: Message): Unit = runBlocking { sendMessage(messageChain) }
|
||||
|
||||
@JvmDefault
|
||||
@JavaFriendlyAPI
|
||||
@JvmName("sendMessage")
|
||||
public fun __sendMessageBlocking(message: String): Unit = runBlocking { sendMessage(message) }
|
||||
}
|
||||
|
||||
/**
|
||||
@ -58,6 +48,7 @@ public interface BotAwareCommandSender : CommandSender {
|
||||
public override val bot: Bot
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
public suspend inline fun CommandSender.sendMessage(message: String): Unit = sendMessage(PlainText(message))
|
||||
|
||||
/**
|
||||
|
@ -18,9 +18,9 @@
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.description.*
|
||||
import net.mamoe.mirai.console.command.internal.AbstractReflectionCommand
|
||||
import net.mamoe.mirai.console.command.internal.CompositeCommandSubCommandAnnotationResolver
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand
|
||||
import net.mamoe.mirai.console.internal.command.CompositeCommandSubCommandAnnotationResolver
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import kotlin.annotation.AnnotationRetention.RUNTIME
|
||||
import kotlin.annotation.AnnotationTarget.FUNCTION
|
||||
import kotlin.reflect.KClass
|
||||
@ -35,13 +35,13 @@ public abstract class CompositeCommand @JvmOverloads constructor(
|
||||
description: String = "no description available",
|
||||
permission: CommandPermission = CommandPermission.Default,
|
||||
prefixOptional: Boolean = false,
|
||||
overrideContext: CommandParserContext = EmptyCommandParserContext
|
||||
overrideContext: CommandArgumentContext = EmptyCommandArgumentContext
|
||||
) : Command, AbstractReflectionCommand(owner, names, description, permission, prefixOptional),
|
||||
CommandParserContextAware {
|
||||
CommandArgumentContextAware {
|
||||
/**
|
||||
* [CommandArgParser] 的环境
|
||||
* [CommandArgumentParser] 的环境
|
||||
*/
|
||||
public final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
||||
public final override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext
|
||||
|
||||
/**
|
||||
* 标记一个函数为子指令, 当 [value] 为空时使用函数名.
|
||||
|
@ -1,5 +1,8 @@
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
/**
|
||||
* 无参数解析, 接收原生参数的指令.
|
||||
*/
|
||||
public abstract class RawCommand(
|
||||
public override val owner: CommandOwner,
|
||||
public override vararg val names: String,
|
||||
|
@ -17,12 +17,12 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.description.CommandParserContext
|
||||
import net.mamoe.mirai.console.command.description.CommandParserContextAware
|
||||
import net.mamoe.mirai.console.command.description.EmptyCommandParserContext
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
|
||||
import net.mamoe.mirai.console.command.description.EmptyCommandArgumentContext
|
||||
import net.mamoe.mirai.console.command.description.plus
|
||||
import net.mamoe.mirai.console.command.internal.AbstractReflectionCommand
|
||||
import net.mamoe.mirai.console.command.internal.SimpleCommandSubCommandAnnotationResolver
|
||||
import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand
|
||||
import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotationResolver
|
||||
|
||||
public abstract class SimpleCommand @JvmOverloads constructor(
|
||||
owner: CommandOwner,
|
||||
@ -30,9 +30,9 @@ public abstract class SimpleCommand @JvmOverloads constructor(
|
||||
description: String = "no description available",
|
||||
permission: CommandPermission = CommandPermission.Default,
|
||||
prefixOptional: Boolean = false,
|
||||
overrideContext: CommandParserContext = EmptyCommandParserContext
|
||||
overrideContext: CommandArgumentContext = EmptyCommandArgumentContext
|
||||
) : Command, AbstractReflectionCommand(owner, names, description, permission, prefixOptional),
|
||||
CommandParserContextAware {
|
||||
CommandArgumentContextAware {
|
||||
|
||||
public override val usage: String
|
||||
get() = super.usage
|
||||
@ -42,7 +42,11 @@ public abstract class SimpleCommand @JvmOverloads constructor(
|
||||
*/
|
||||
protected annotation class Handler
|
||||
|
||||
public final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
||||
public final override val context: CommandArgumentContext = CommandArgumentContext.Builtins + overrideContext
|
||||
|
||||
public final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
||||
subCommands.single().parseAndExecute(this, args, false)
|
||||
}
|
||||
|
||||
internal override fun checkSubCommand(subCommands: Array<SubCommandDescriptor>) {
|
||||
super.checkSubCommand(subCommands)
|
||||
@ -52,10 +56,6 @@ public abstract class SimpleCommand @JvmOverloads constructor(
|
||||
@Deprecated("prohibited", level = DeprecationLevel.HIDDEN)
|
||||
internal override suspend fun CommandSender.onDefault(rawArgs: Array<out Any>) = sendMessage(usage)
|
||||
|
||||
public final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
||||
subCommands.single().parseAndExecute(this, args, false)
|
||||
}
|
||||
|
||||
internal final override val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
||||
get() = SimpleCommandSubCommandAnnotationResolver
|
||||
}
|
@ -14,7 +14,7 @@ import net.mamoe.mirai.console.command.BotAwareCommandSender
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.MemberCommandSender
|
||||
import net.mamoe.mirai.console.command.UserCommandSender
|
||||
import net.mamoe.mirai.console.command.internal.fuzzySearchMember
|
||||
import net.mamoe.mirai.console.internal.command.fuzzySearchMember
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
@ -23,43 +23,43 @@ import net.mamoe.mirai.message.data.SingleMessage
|
||||
import net.mamoe.mirai.message.data.content
|
||||
|
||||
|
||||
public object IntArgParser : CommandArgParser<Int> {
|
||||
public object IntArgumentParser : CommandArgumentParser<Int> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Int =
|
||||
raw.toIntOrNull() ?: illegalArgument("无法解析 $raw 为整数")
|
||||
}
|
||||
|
||||
public object LongArgParser : CommandArgParser<Long> {
|
||||
public object LongArgumentParser : CommandArgumentParser<Long> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Long =
|
||||
raw.toLongOrNull() ?: illegalArgument("无法解析 $raw 为长整数")
|
||||
}
|
||||
|
||||
public object ShortArgParser : CommandArgParser<Short> {
|
||||
public object ShortArgumentParser : CommandArgumentParser<Short> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Short =
|
||||
raw.toShortOrNull() ?: illegalArgument("无法解析 $raw 为短整数")
|
||||
}
|
||||
|
||||
public object ByteArgParser : CommandArgParser<Byte> {
|
||||
public object ByteArgumentParser : CommandArgumentParser<Byte> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Byte =
|
||||
raw.toByteOrNull() ?: illegalArgument("无法解析 $raw 为字节")
|
||||
}
|
||||
|
||||
public object DoubleArgParser : CommandArgParser<Double> {
|
||||
public object DoubleArgumentParser : CommandArgumentParser<Double> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Double =
|
||||
raw.toDoubleOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||
}
|
||||
|
||||
public object FloatArgParser : CommandArgParser<Float> {
|
||||
public object FloatArgumentParser : CommandArgumentParser<Float> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Float =
|
||||
raw.toFloatOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||
}
|
||||
|
||||
public object StringArgParser : CommandArgParser<String> {
|
||||
public object StringArgumentParser : CommandArgumentParser<String> {
|
||||
public override fun parse(raw: String, sender: CommandSender): String {
|
||||
return raw
|
||||
}
|
||||
}
|
||||
|
||||
public object BooleanArgParser : CommandArgParser<Boolean> {
|
||||
public object BooleanArgumentParser : CommandArgumentParser<Boolean> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str ->
|
||||
str.equals("true", ignoreCase = true)
|
||||
|| str.equals("yes", ignoreCase = true)
|
||||
@ -73,14 +73,14 @@ public object BooleanArgParser : CommandArgParser<Boolean> {
|
||||
* output: Bot
|
||||
* errors: String->Int convert, Bot Not Exist
|
||||
*/
|
||||
public object ExistBotArgParser : CommandArgParser<Bot> {
|
||||
public object ExistBotArgumentParser : CommandArgumentParser<Bot> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Bot {
|
||||
val uin = raw.toLongOrNull() ?: illegalArgument("无法识别 QQ ID: $raw")
|
||||
return Bot.getInstanceOrNull(uin) ?: illegalArgument("无法找到 Bot $uin")
|
||||
}
|
||||
}
|
||||
|
||||
public object ExistFriendArgParser : CommandArgParser<Friend> {
|
||||
public object ExistFriendArgumentParser : CommandArgumentParser<Friend> {
|
||||
//Bot.friend
|
||||
//friend
|
||||
//~ = self
|
||||
@ -125,7 +125,7 @@ public object ExistFriendArgParser : CommandArgParser<Friend> {
|
||||
}
|
||||
}
|
||||
|
||||
public object ExistGroupArgParser : CommandArgParser<Group> {
|
||||
public object ExistGroupArgumentParser : CommandArgumentParser<Group> {
|
||||
public override fun parse(raw: String, sender: CommandSender): Group {
|
||||
//by default
|
||||
if ((raw == "" || raw == "~") && sender is MemberCommandSender) {
|
||||
@ -160,7 +160,7 @@ public object ExistGroupArgParser : CommandArgParser<Group> {
|
||||
}
|
||||
}
|
||||
|
||||
public object ExistMemberArgParser : CommandArgParser<Member> {
|
||||
public object ExistMemberArgumentParser : CommandArgumentParser<Member> {
|
||||
//后台: Bot.Group.Member[QQ/名片]
|
||||
//私聊: Group.Member[QQ/名片]
|
||||
//群内: Q号
|
||||
|
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "unused", "MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.mamoe.mirai.console.command.description
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.CompositeCommand
|
||||
import net.mamoe.mirai.console.command.SimpleCommand
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext.ParserPair
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
|
||||
/**
|
||||
* [CommandArgumentParser] 的集合, 用于 [CompositeCommand] 和 [SimpleCommand].
|
||||
*
|
||||
* @see SimpleCommandArgumentContext 简单实现
|
||||
* @see EmptyCommandArgumentContext 空实现, 类似 [emptyList]
|
||||
* @see CommandArgumentContext.EMPTY 空实现的另一种获取方式.
|
||||
*
|
||||
* @see CommandArgumentContext.Builtins 内建 [CommandArgumentParser]
|
||||
*
|
||||
* @see CommandArgumentContext DSL
|
||||
*/
|
||||
public interface CommandArgumentContext {
|
||||
/**
|
||||
* [KClass] 到 [CommandArgumentParser] 的匹配
|
||||
*/
|
||||
public data class ParserPair<T : Any>(
|
||||
val klass: KClass<T>,
|
||||
val parser: CommandArgumentParser<T>
|
||||
)
|
||||
|
||||
public operator fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>?
|
||||
|
||||
public fun toList(): List<ParserPair<*>>
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
* For Java callers.
|
||||
*
|
||||
* @see [EmptyCommandArgumentContext]
|
||||
*/
|
||||
@JvmStatic
|
||||
public val EMPTY: CommandArgumentContext = EmptyCommandArgumentContext
|
||||
}
|
||||
|
||||
/**
|
||||
* 内建的默认 [CommandArgumentParser]
|
||||
*/
|
||||
public object Builtins : CommandArgumentContext by (CommandArgumentContext {
|
||||
Int::class with IntArgumentParser
|
||||
Byte::class with ByteArgumentParser
|
||||
Short::class with ShortArgumentParser
|
||||
Boolean::class with BooleanArgumentParser
|
||||
String::class with StringArgumentParser
|
||||
Long::class with LongArgumentParser
|
||||
Double::class with DoubleArgumentParser
|
||||
Float::class with FloatArgumentParser
|
||||
|
||||
Member::class with ExistMemberArgumentParser
|
||||
Group::class with ExistGroupArgumentParser
|
||||
Bot::class with ExistBotArgumentParser
|
||||
Friend::class with ExistFriendArgumentParser
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拥有 [CommandArgumentContext] 的类
|
||||
*
|
||||
* @see SimpleCommand
|
||||
* @see CompositeCommand
|
||||
*/
|
||||
public interface CommandArgumentContextAware {
|
||||
/**
|
||||
* [CommandArgumentParser] 的集合
|
||||
*/
|
||||
public val context: CommandArgumentContext
|
||||
}
|
||||
|
||||
public object EmptyCommandArgumentContext : CommandArgumentContext by SimpleCommandArgumentContext(listOf())
|
||||
|
||||
/**
|
||||
* 合并两个 [CommandArgumentContext], [replacer] 将会替换 [this] 中重复的 parser.
|
||||
*/
|
||||
public operator fun CommandArgumentContext.plus(replacer: CommandArgumentContext): CommandArgumentContext {
|
||||
if (replacer == EmptyCommandArgumentContext) return this
|
||||
if (this == EmptyCommandArgumentContext) return replacer
|
||||
return object : CommandArgumentContext {
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
|
||||
replacer[klass] ?: this@plus[klass]
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并 [this] 与 [replacer], [replacer] 将会替换 [this] 中重复的 parser.
|
||||
*/
|
||||
public operator fun CommandArgumentContext.plus(replacer: List<ParserPair<*>>): CommandArgumentContext {
|
||||
if (replacer.isEmpty()) return this
|
||||
if (this == EmptyCommandArgumentContext) return SimpleCommandArgumentContext(replacer)
|
||||
return object : CommandArgumentContext {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
|
||||
replacer.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgumentParser<T>?
|
||||
?: this@plus[klass]
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 自定义 [CommandArgumentContext]
|
||||
*
|
||||
* @see CommandArgumentContext
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public class SimpleCommandArgumentContext(
|
||||
public val list: List<ParserPair<*>>
|
||||
) : CommandArgumentContext {
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgumentParser<T>? =
|
||||
this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgumentParser<T>?
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = list
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个 [CommandArgumentContext].
|
||||
*
|
||||
* ```
|
||||
* CommandArgumentContext {
|
||||
* Int::class with IntArgParser
|
||||
* Member::class with ExistMemberArgParser
|
||||
* Group::class with { s: String, sender: CommandSender ->
|
||||
* Bot.getInstance(s.toLong()).getGroup(s.toLong())
|
||||
* }
|
||||
* Bot::class with { s: String ->
|
||||
* Bot.getInstance(s.toLong())
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @see CommandArgumentContextBuilder
|
||||
* @see CommandArgumentContext
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
@JvmSynthetic
|
||||
public inline fun CommandArgumentContext(block: CommandArgumentContextBuilder.() -> Unit): CommandArgumentContext {
|
||||
return SimpleCommandArgumentContext(CommandArgumentContextBuilder().apply(block).distinctByReversed { it.klass })
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CommandArgumentContext
|
||||
*/
|
||||
public class CommandArgumentContextBuilder : MutableList<ParserPair<*>> by mutableListOf() {
|
||||
@JvmName("add")
|
||||
public inline infix fun <T : Any> KClass<T>.with(parser: CommandArgumentParser<T>): ParserPair<*> =
|
||||
ParserPair(this, parser).also { add(it) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgumentParser<T>.(s: String, sender: CommandSender) -> T
|
||||
): ParserPair<*> = ParserPair(this, CommandArgParser(parser)).also { add(it) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgumentParser<T>.(s: String) -> T
|
||||
): ParserPair<*> = ParserPair(this, CommandArgParser { s: String, _: CommandSender -> parser(s) }).also { add(it) }
|
||||
|
||||
@JvmSynthetic
|
||||
public inline fun <reified T : Any> add(parser: CommandArgumentParser<T>): ParserPair<*> =
|
||||
ParserPair(T::class, parser).also { add(it) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@JvmSynthetic
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgumentParser<*>.(s: String) -> T
|
||||
): ParserPair<*> = T::class with CommandArgParser { s: String, _: CommandSender -> parser(s) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@JvmSynthetic
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgumentParser<*>.(s: String, sender: CommandSender) -> T
|
||||
): ParserPair<*> = T::class with CommandArgParser(parser)
|
||||
}
|
||||
|
||||
|
||||
@PublishedApi
|
||||
internal inline fun <T, K> List<T>.distinctByReversed(selector: (T) -> K): List<T> {
|
||||
val set = HashSet<K>()
|
||||
val list = ArrayList<T>()
|
||||
for (i in this.indices.reversed()) {
|
||||
val element = this[i]
|
||||
if (set.add(element.let(selector))) {
|
||||
list.add(element)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
@ -17,17 +17,18 @@ import net.mamoe.mirai.message.data.content
|
||||
import kotlin.contracts.contract
|
||||
|
||||
/**
|
||||
* this output type of that arg
|
||||
* input is always String
|
||||
* 指令参数解析器.
|
||||
*
|
||||
* @see CommandArgumentContext
|
||||
*/
|
||||
public interface CommandArgParser<out T : Any> {
|
||||
public interface CommandArgumentParser<out T : Any> {
|
||||
public fun parse(raw: String, sender: CommandSender): T
|
||||
|
||||
@JvmDefault
|
||||
public fun parse(raw: SingleMessage, sender: CommandSender): T = parse(raw.content, sender)
|
||||
}
|
||||
|
||||
public fun <T : Any> CommandArgParser<T>.parse(raw: Any, sender: CommandSender): T {
|
||||
public fun <T : Any> CommandArgumentParser<T>.parse(raw: Any, sender: CommandSender): T {
|
||||
contract {
|
||||
returns() implies (raw is String || raw is SingleMessage)
|
||||
}
|
||||
@ -41,12 +42,12 @@ public fun <T : Any> CommandArgParser<T>.parse(raw: Any, sender: CommandSender):
|
||||
|
||||
@Suppress("unused")
|
||||
@JvmSynthetic
|
||||
public inline fun CommandArgParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
||||
public inline fun CommandArgumentParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
||||
throw ParserException(message, cause)
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
public inline fun CommandArgParser<*>.checkArgument(
|
||||
public inline fun CommandArgumentParser<*>.checkArgument(
|
||||
condition: Boolean,
|
||||
crossinline message: () -> String = { "Check failed." }
|
||||
) {
|
||||
@ -57,25 +58,25 @@ public inline fun CommandArgParser<*>.checkArgument(
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建匿名 [CommandArgParser]
|
||||
* 创建匿名 [CommandArgumentParser]
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
@JvmSynthetic
|
||||
public inline fun <T : Any> CommandArgParser(
|
||||
crossinline stringParser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T
|
||||
): CommandArgParser<T> = object : CommandArgParser<T> {
|
||||
crossinline stringParser: CommandArgumentParser<T>.(s: String, sender: CommandSender) -> T
|
||||
): CommandArgumentParser<T> = object : CommandArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = stringParser(raw, sender)
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建匿名 [CommandArgParser]
|
||||
* 创建匿名 [CommandArgumentParser]
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
@JvmSynthetic
|
||||
public inline fun <T : Any> CommandArgParser(
|
||||
crossinline stringParser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T,
|
||||
crossinline messageParser: CommandArgParser<T>.(m: SingleMessage, sender: CommandSender) -> T
|
||||
): CommandArgParser<T> = object : CommandArgParser<T> {
|
||||
crossinline stringParser: CommandArgumentParser<T>.(s: String, sender: CommandSender) -> T,
|
||||
crossinline messageParser: CommandArgumentParser<T>.(m: SingleMessage, sender: CommandSender) -> T
|
||||
): CommandArgumentParser<T> = object : CommandArgumentParser<T> {
|
||||
override fun parse(raw: String, sender: CommandSender): T = stringParser(raw, sender)
|
||||
override fun parse(raw: SingleMessage, sender: CommandSender): T = messageParser(raw, sender)
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 Mamoe Technologies and contributors.
|
||||
*
|
||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "unused", "MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.mamoe.mirai.console.command.description
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.command.CommandSender
|
||||
import net.mamoe.mirai.console.command.description.CommandParserContext.ParserPair
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.contact.Friend
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
|
||||
/**
|
||||
* [KClass] 到 [CommandArgParser] 的匹配
|
||||
* @see CustomCommandParserContext 自定义
|
||||
*/
|
||||
public interface CommandParserContext {
|
||||
public data class ParserPair<T : Any>(
|
||||
val klass: KClass<T>,
|
||||
val parser: CommandArgParser<T>
|
||||
)
|
||||
|
||||
public operator fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>?
|
||||
|
||||
public fun toList(): List<ParserPair<*>>
|
||||
|
||||
/**
|
||||
* 内建的默认 [CommandArgParser]
|
||||
*/
|
||||
public object Builtins : CommandParserContext by (CommandParserContext {
|
||||
Int::class with IntArgParser
|
||||
Byte::class with ByteArgParser
|
||||
Short::class with ShortArgParser
|
||||
Boolean::class with BooleanArgParser
|
||||
String::class with StringArgParser
|
||||
Long::class with LongArgParser
|
||||
Double::class with DoubleArgParser
|
||||
Float::class with FloatArgParser
|
||||
|
||||
Member::class with ExistMemberArgParser
|
||||
Group::class with ExistGroupArgParser
|
||||
Bot::class with ExistBotArgParser
|
||||
Friend::class with ExistFriendArgParser
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* 拥有 [CommandParserContext] 的类
|
||||
*/
|
||||
public interface CommandParserContextAware {
|
||||
/**
|
||||
* [CommandArgParser] 的环境
|
||||
*/
|
||||
public val context: CommandParserContext
|
||||
}
|
||||
|
||||
public object EmptyCommandParserContext : CommandParserContext by CustomCommandParserContext(listOf())
|
||||
|
||||
/**
|
||||
* 合并两个 [CommandParserContext], [replacer] 将会替换 [this] 中重复的 parser.
|
||||
*/
|
||||
public operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandParserContext {
|
||||
if (replacer == EmptyCommandParserContext) return this
|
||||
if (this == EmptyCommandParserContext) return replacer
|
||||
return object : CommandParserContext {
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>? = replacer[klass] ?: this@plus[klass]
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 合并 [this] 与 [replacer], [replacer] 将会替换 [this] 中重复的 parser.
|
||||
*/
|
||||
public operator fun CommandParserContext.plus(replacer: List<ParserPair<*>>): CommandParserContext {
|
||||
if (replacer.isEmpty()) return this
|
||||
if (this == EmptyCommandParserContext) return CustomCommandParserContext(replacer)
|
||||
return object : CommandParserContext {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>? =
|
||||
replacer.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgParser<T>? ?: this@plus[klass]
|
||||
|
||||
override fun toList(): List<ParserPair<*>> = replacer.toList() + this@plus.toList()
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public open class CustomCommandParserContext(public val list: List<ParserPair<*>>) : CommandParserContext {
|
||||
|
||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>? =
|
||||
this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgParser<T>?
|
||||
|
||||
override fun toList(): List<ParserPair<*>> {
|
||||
return list
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建一个 [CommandParserContext].
|
||||
*
|
||||
* ```
|
||||
* CommandParserContext {
|
||||
* Int::class with IntArgParser
|
||||
* Member::class with ExistMemberArgParser
|
||||
* Group::class with { s: String, sender: CommandSender ->
|
||||
* Bot.getInstance(s.toLong()).getGroup(s.toLong())
|
||||
* }
|
||||
* Bot::class with { s: String ->
|
||||
* Bot.getInstance(s.toLong())
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
@JvmSynthetic
|
||||
public inline fun CommandParserContext(block: CommandParserContextBuilder.() -> Unit): CommandParserContext {
|
||||
return CustomCommandParserContext(CommandParserContextBuilder().apply(block).distinctByReversed { it.klass })
|
||||
}
|
||||
|
||||
/**
|
||||
* @see CommandParserContext
|
||||
*/
|
||||
public class CommandParserContextBuilder : MutableList<ParserPair<*>> by mutableListOf() {
|
||||
@JvmName("add")
|
||||
public inline infix fun <T : Any> KClass<T>.with(parser: CommandArgParser<T>): ParserPair<*> =
|
||||
ParserPair(this, parser).also { add(it) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@JvmSynthetic
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T
|
||||
): ParserPair<*> = ParserPair(this, CommandArgParser(parser)).also { add(it) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@JvmSynthetic
|
||||
public inline infix fun <T : Any> KClass<T>.with(
|
||||
crossinline parser: CommandArgParser<T>.(s: String) -> T
|
||||
): ParserPair<*> = ParserPair(this, CommandArgParser { s: String, _: CommandSender -> parser(s) }).also { add(it) }
|
||||
|
||||
@JvmSynthetic
|
||||
public inline fun <reified T : Any> add(parser: CommandArgParser<T>): ParserPair<*> =
|
||||
ParserPair(T::class, parser).also { add(it) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@JvmSynthetic
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgParser<*>.(s: String) -> T
|
||||
): ParserPair<*> = T::class with CommandArgParser { s: String, _: CommandSender -> parser(s) }
|
||||
|
||||
/**
|
||||
* 添加一个指令解析器
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@JvmSynthetic
|
||||
@LowPriorityInOverloadResolution
|
||||
public inline infix fun <reified T : Any> add(
|
||||
crossinline parser: CommandArgParser<*>.(s: String, sender: CommandSender) -> T
|
||||
): ParserPair<*> = T::class with CommandArgParser(parser)
|
||||
}
|
||||
|
||||
|
||||
@PublishedApi
|
||||
internal inline fun <T, K> List<T>.distinctByReversed(selector: (T) -> K): List<T> {
|
||||
val set = HashSet<K>()
|
||||
val list = ArrayList<T>()
|
||||
for (i in this.indices.reversed()) {
|
||||
val element = this[i]
|
||||
if (set.add(element.let(selector))) {
|
||||
list.add(element)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
@ -34,24 +34,24 @@ internal data class CommandParam<T : Any>(
|
||||
*/
|
||||
val name: String,
|
||||
/**
|
||||
* 参数类型. 将从 [CompositeCommand.context] 中寻找 [CommandArgParser] 解析.
|
||||
* 参数类型. 将从 [CompositeCommand.context] 中寻找 [CommandArgumentParser] 解析.
|
||||
*/
|
||||
val type: KClass<T> // exact type
|
||||
) {
|
||||
constructor(name: String, type: KClass<T>, parser: CommandArgParser<T>) : this(name, type) {
|
||||
constructor(name: String, type: KClass<T>, parser: CommandArgumentParser<T>) : this(name, type) {
|
||||
this._overrideParser = parser
|
||||
}
|
||||
|
||||
@Suppress("PropertyName")
|
||||
@JvmField
|
||||
internal var _overrideParser: CommandArgParser<T>? = null
|
||||
internal var _overrideParser: CommandArgumentParser<T>? = null
|
||||
|
||||
|
||||
/**
|
||||
* 覆盖的 [CommandArgParser].
|
||||
* 覆盖的 [CommandArgumentParser].
|
||||
*
|
||||
* 如果非 `null`, 将不会从 [CommandParserContext] 寻找 [CommandArgParser]
|
||||
* 如果非 `null`, 将不会从 [CommandArgumentContext] 寻找 [CommandArgumentParser]
|
||||
*/
|
||||
val overrideParser: CommandArgParser<T>? get() = _overrideParser
|
||||
val overrideParser: CommandArgumentParser<T>? get() = _overrideParser
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,9 @@
|
||||
package net.mamoe.mirai.console.internal
|
||||
|
||||
import java.util.*
|
||||
|
||||
internal object MiraiConsoleBuildConstants { // auto-filled on build (task :mirai-console:fillBuildConstants)
|
||||
@JvmStatic
|
||||
val buildDate: Date = Date(1596350800177L) // 2020-08-02 14:46:40
|
||||
const val version: String = "1.0-M1"
|
||||
}
|
@ -0,0 +1,88 @@
|
||||
@file:OptIn(ConsoleExperimentalAPI::class)
|
||||
|
||||
package net.mamoe.mirai.console.internal
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.IllegalMiraiConsoleImplementationError
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.MiraiConsoleFrontEnd
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementation
|
||||
import net.mamoe.mirai.console.command.BuiltInCommands
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
import net.mamoe.mirai.console.command.CommandManagerImpl
|
||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||
import net.mamoe.mirai.console.internal.plugin.CuiPluginCenter
|
||||
import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl
|
||||
import net.mamoe.mirai.console.internal.utils.ConsoleBuiltInSettingStorage
|
||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.PluginManager
|
||||
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.utils.DefaultLogger
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.mirai.utils.info
|
||||
import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
* [MiraiConsole] 公开 API 与前端实现的连接桥.
|
||||
*/
|
||||
internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleImplementation,
|
||||
MiraiConsole {
|
||||
override val pluginCenter: PluginCenter get() = CuiPluginCenter
|
||||
|
||||
private val instance: MiraiConsoleImplementation get() = MiraiConsoleImplementation.instance
|
||||
override val buildDate: Date get() = MiraiConsoleBuildConstants.buildDate
|
||||
override val version: String get() = MiraiConsoleBuildConstants.version
|
||||
override val rootDir: File get() = instance.rootDir
|
||||
override val frontEnd: MiraiConsoleFrontEnd get() = instance.frontEnd
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
override val mainLogger: MiraiLogger
|
||||
get() = instance.mainLogger
|
||||
override val coroutineContext: CoroutineContext get() = instance.coroutineContext
|
||||
override val builtInPluginLoaders: List<PluginLoader<*, *>> get() = instance.builtInPluginLoaders
|
||||
override val consoleCommandSender: ConsoleCommandSender get() = instance.consoleCommandSender
|
||||
|
||||
override val settingStorageForJarPluginLoader: SettingStorage get() = instance.settingStorageForJarPluginLoader
|
||||
override val settingStorageForBuiltIns: SettingStorage get() = instance.settingStorageForBuiltIns
|
||||
|
||||
init {
|
||||
DefaultLogger = { identity -> this.newLogger(identity) }
|
||||
}
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
override fun newLogger(identity: String?): MiraiLogger = frontEnd.loggerFor(identity)
|
||||
|
||||
@OptIn(ConsoleExperimentalAPI::class)
|
||||
internal fun doStart() {
|
||||
val buildDateFormatted = SimpleDateFormat("yyyy-MM-dd").format(buildDate)
|
||||
mainLogger.info { "Starting mirai-console..." }
|
||||
mainLogger.info { "Backend: version $version, built on $buildDateFormatted." }
|
||||
mainLogger.info { "Frontend ${frontEnd.name}: version $version." }
|
||||
|
||||
if (coroutineContext[Job] == null) {
|
||||
throw IllegalMiraiConsoleImplementationError("The coroutineContext given to MiraiConsole must have a Job in it.")
|
||||
}
|
||||
MiraiConsole.job.invokeOnCompletion {
|
||||
Bot.botInstances.forEach { kotlin.runCatching { it.close() }.exceptionOrNull()?.let(mainLogger::error) }
|
||||
}
|
||||
|
||||
BuiltInCommands.registerAll()
|
||||
mainLogger.info { "Preparing built-in commands: ${BuiltInCommands.all.joinToString { it.primaryName }}" }
|
||||
CommandManagerImpl.commandListener // start
|
||||
|
||||
mainLogger.info { "Loading plugins..." }
|
||||
PluginManagerImpl.loadEnablePlugins()
|
||||
mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." }
|
||||
mainLogger.info { "mirai-console started successfully." }
|
||||
|
||||
ConsoleBuiltInSettingStorage // init
|
||||
// Only for initialize
|
||||
}
|
||||
}
|
@ -9,12 +9,13 @@
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "MemberVisibilityCanBePrivate", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.console.command.internal
|
||||
package net.mamoe.mirai.console.internal.command
|
||||
|
||||
import net.mamoe.mirai.console.command.*
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
|
||||
import net.mamoe.mirai.console.command.description.CommandParam
|
||||
import net.mamoe.mirai.console.command.description.CommandParserContext
|
||||
import net.mamoe.mirai.console.command.description.CommandParserContextAware
|
||||
import net.mamoe.mirai.message.data.PlainText
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
import kotlin.reflect.KAnnotatedElement
|
||||
@ -43,11 +44,11 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
||||
prefixOptional: Boolean = false
|
||||
) : Command, AbstractCommand(
|
||||
owner,
|
||||
names = *names,
|
||||
names = names,
|
||||
description = description,
|
||||
permission = permission,
|
||||
prefixOptional = prefixOptional
|
||||
), CommandParserContextAware {
|
||||
), CommandArgumentContextAware {
|
||||
internal abstract val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
||||
|
||||
@JvmField
|
||||
@ -101,7 +102,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
||||
map[name] = descriptor
|
||||
}
|
||||
}
|
||||
map.toSortedMap(Comparator { o1, o2 -> o1!!.contentHashCode() - o2!!.contentHashCode() })
|
||||
map.toSortedMap { o1, o2 -> o1!!.contentHashCode() - o2!!.contentHashCode() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,7 +118,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
||||
val description: String,
|
||||
val permission: CommandPermission,
|
||||
val onCommand: suspend (sender: CommandSender, parsedArgs: Array<out Any>) -> Boolean,
|
||||
val context: CommandParserContext,
|
||||
val context: CommandArgumentContext,
|
||||
val usage: String
|
||||
) {
|
||||
internal suspend inline fun parseAndExecute(
|
||||
@ -210,7 +211,7 @@ internal val KClass<*>.qualifiedNameOrTip: String get() = this.qualifiedName ?:
|
||||
|
||||
internal fun AbstractReflectionCommand.createSubCommand(
|
||||
function: KFunction<*>,
|
||||
context: CommandParserContext
|
||||
context: CommandArgumentContext
|
||||
): AbstractReflectionCommand.SubCommandDescriptor {
|
||||
val notStatic = !function.hasAnnotation<JvmStatic>()
|
||||
val overridePermission = function.findAnnotation<CompositeCommand.Permission>()//optional
|
@ -7,17 +7,11 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.command.internal
|
||||
package net.mamoe.mirai.console.internal.command
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.command.*
|
||||
import net.mamoe.mirai.contact.Group
|
||||
import net.mamoe.mirai.contact.Member
|
||||
import net.mamoe.mirai.event.Listener
|
||||
import net.mamoe.mirai.event.subscribeAlways
|
||||
import net.mamoe.mirai.message.MessageEvent
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
|
||||
|
||||
internal infix fun Array<String>.matchesBeginning(list: List<Any>): Boolean {
|
||||
@ -27,54 +21,6 @@ internal infix fun Array<String>.matchesBeginning(list: List<Any>): Boolean {
|
||||
return true
|
||||
}
|
||||
|
||||
internal object InternalCommandManager : CoroutineScope by CoroutineScope(MiraiConsole.job) {
|
||||
const val COMMAND_PREFIX = "/"
|
||||
|
||||
@JvmField
|
||||
internal val registeredCommands: MutableList<Command> = mutableListOf()
|
||||
|
||||
/**
|
||||
* 全部注册的指令
|
||||
* /mute -> MuteCommand
|
||||
* /jinyan -> MuteCommand
|
||||
*/
|
||||
@JvmField
|
||||
internal val requiredPrefixCommandMap: MutableMap<String, Command> = mutableMapOf()
|
||||
|
||||
/**
|
||||
* Command name of commands that are prefix optional
|
||||
* mute -> MuteCommand
|
||||
*/
|
||||
@JvmField
|
||||
internal val optionalPrefixCommandMap: MutableMap<String, Command> = mutableMapOf()
|
||||
|
||||
@JvmField
|
||||
internal val modifyLock = ReentrantLock()
|
||||
|
||||
|
||||
/**
|
||||
* 从原始的 command 中解析出 Command 对象
|
||||
*/
|
||||
internal fun matchCommand(rawCommand: String): Command? {
|
||||
if (rawCommand.startsWith(COMMAND_PREFIX)) {
|
||||
return requiredPrefixCommandMap[rawCommand.substringAfter(COMMAND_PREFIX).toLowerCase()]
|
||||
}
|
||||
return optionalPrefixCommandMap[rawCommand.toLowerCase()]
|
||||
}
|
||||
|
||||
internal val commandListener: Listener<MessageEvent> by lazy {
|
||||
@Suppress("RemoveExplicitTypeArguments")
|
||||
subscribeAlways<MessageEvent>(
|
||||
concurrency = Listener.ConcurrencyKind.CONCURRENT,
|
||||
priority = Listener.EventPriority.HIGH
|
||||
) {
|
||||
if (this.sender.asCommandSender().executeCommand(message) != null) {
|
||||
intercept()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal infix fun Array<out String>.intersectsIgnoringCase(other: Array<out String>): Boolean {
|
||||
val max = this.size.coerceAtMost(other.size)
|
||||
for (i in 0 until max) {
|
||||
@ -186,7 +132,7 @@ internal suspend inline fun CommandSender.matchAndExecuteCommandInternal(
|
||||
messages: Any,
|
||||
commandName: String
|
||||
): Command? {
|
||||
val command = InternalCommandManager.matchCommand(
|
||||
val command = CommandManagerImpl.matchCommand(
|
||||
commandName
|
||||
) ?: return null
|
||||
|
||||
@ -215,4 +161,38 @@ internal suspend inline fun CommandSender.executeCommandInternal(
|
||||
}.onFailure {
|
||||
throw CommandExecutionException(command, commandName, it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@JvmSynthetic
|
||||
internal suspend inline fun CommandSender.executeCommandDetailedInternal(
|
||||
messages: Any,
|
||||
commandName: String
|
||||
): CommandExecuteResult {
|
||||
val command =
|
||||
CommandManagerImpl.matchCommand(commandName) ?: return CommandExecuteResult.CommandNotFound(commandName)
|
||||
val args = messages.flattenCommandComponents().dropToTypedArray(1)
|
||||
|
||||
if (!command.testPermission(this)) {
|
||||
return CommandExecuteResult.PermissionDenied(command, commandName)
|
||||
}
|
||||
kotlin.runCatching {
|
||||
command.onCommand(this, args)
|
||||
}.fold(
|
||||
onSuccess = {
|
||||
return CommandExecuteResult.Success(
|
||||
commandName = commandName,
|
||||
command = command,
|
||||
args = args
|
||||
)
|
||||
},
|
||||
onFailure = {
|
||||
return CommandExecuteResult.ExecutionException(
|
||||
commandName = commandName,
|
||||
command = command,
|
||||
exception = it,
|
||||
args = args
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
|
||||
@file:OptIn(ConsoleExperimentalAPI::class)
|
||||
|
||||
package net.mamoe.mirai.console.plugin.center
|
||||
package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
@ -17,8 +17,9 @@ import io.ktor.client.request.*
|
||||
import io.ktor.util.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.utils.retryCatching
|
||||
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.retryCatching
|
||||
import java.io.File
|
||||
|
||||
internal val json = Json {
|
@ -7,18 +7,18 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.plugin.internal
|
||||
package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.plugin.AbstractFilePluginLoader
|
||||
import net.mamoe.mirai.console.plugin.PluginLoadException
|
||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import java.io.File
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.plugin.internal
|
||||
package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import kotlinx.atomicfu.AtomicLong
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
@ -20,7 +20,7 @@ import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.PluginManager
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription
|
||||
import net.mamoe.mirai.console.utils.ResourceContainer.Companion.asResourceContainer
|
||||
import net.mamoe.mirai.console.util.ResourceContainer.Companion.asResourceContainer
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import java.io.File
|
||||
import java.io.InputStream
|
@ -9,12 +9,12 @@
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "unused")
|
||||
|
||||
package net.mamoe.mirai.console.plugin.jvm
|
||||
package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import kotlinx.atomicfu.locks.withLock
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.internal.setting.cast
|
||||
import net.mamoe.mirai.console.plugin.*
|
||||
import net.mamoe.mirai.console.setting.internal.cast
|
||||
import net.mamoe.mirai.utils.info
|
||||
import java.io.File
|
||||
import java.util.concurrent.locks.ReentrantLock
|
||||
@ -120,7 +120,7 @@ internal object PluginManagerImpl : PluginManager {
|
||||
@Throws(PluginMissingDependencyException::class)
|
||||
private fun loadAndEnableLoaderProviders(): List<PluginDescriptionWithLoader> {
|
||||
val allDescriptions =
|
||||
this.builtInLoaders.listAllPlugins()
|
||||
builtInLoaders.listAllPlugins()
|
||||
.asSequence()
|
||||
.onEach { (loader, descriptions) ->
|
||||
loader as PluginLoader<Plugin, PluginDescription>
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.plugin.internal
|
||||
package net.mamoe.mirai.console.internal.plugin
|
||||
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import java.io.File
|
@ -9,7 +9,7 @@
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import net.mamoe.mirai.console.setting.*
|
||||
|
@ -7,13 +7,12 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import com.vdurmont.semver4j.Semver
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializer
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.internal.map
|
||||
|
||||
@Serializer(forClass = Semver::class)
|
||||
internal object SemverAsStringSerializerLoose : KSerializer<Semver> by String.serializer().map(
|
@ -9,7 +9,7 @@
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import net.mamoe.mirai.console.setting.SerializableValue.Companion.serializableValueWith
|
@ -9,7 +9,7 @@
|
||||
|
||||
@file:Suppress("INVISIBLE_REFERENCE", "INVISIBLE_MEMBER", "EXPOSED_SUPER_CLASS")
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialName
|
@ -7,19 +7,19 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.atomicfu.atomic
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import net.mamoe.mirai.console.command.internal.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.plugin.internal.updateWhen
|
||||
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.internal.plugin.updateWhen
|
||||
import net.mamoe.mirai.console.plugin.jvm.loadSetting
|
||||
import net.mamoe.mirai.console.setting.*
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.utils.currentTimeMillis
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import java.io.File
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.builtins.serializer
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
@ -7,9 +7,9 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import net.mamoe.mirai.console.command.internal.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
@ -9,7 +9,7 @@
|
||||
|
||||
@file:Suppress("DuplicatedCode")
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.serialization.UnsafeSerializationApi
|
||||
import kotlinx.serialization.serializer
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.UnsafeSerializationApi
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
package net.mamoe.mirai.console.internal.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialName
|
@ -6,41 +6,42 @@
|
||||
*
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
@file:JvmName("BotManagers")
|
||||
@file:Suppress("MemberVisibilityCanBePrivate")
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
package net.mamoe.mirai.console.internal.utils
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge
|
||||
import net.mamoe.mirai.console.setting.*
|
||||
import net.mamoe.mirai.console.setting.SettingStorage.Companion.load
|
||||
import net.mamoe.mirai.console.util.BotManager
|
||||
import net.mamoe.mirai.contact.User
|
||||
import net.mamoe.mirai.utils.minutesToMillis
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
internal object BotManagerImpl : BotManager {
|
||||
/**
|
||||
* 判断此用户是否为 console 管理员
|
||||
*/
|
||||
override val User.isManager: Boolean get() = this.id in this.bot.managers
|
||||
|
||||
/**
|
||||
* 判断此用户是否为 console 管理员
|
||||
*/
|
||||
public val User.isManager: Boolean get() = this.id in this.bot.managers
|
||||
override fun Bot.removeManager(id: Long): Boolean {
|
||||
return ManagersConfig[this].remove(id)
|
||||
}
|
||||
|
||||
public fun Bot.removeManager(id: Long): Boolean {
|
||||
return ManagersConfig[this].remove(id)
|
||||
override val Bot.managers: List<Long>
|
||||
get() = ManagersConfig[this].toList()
|
||||
|
||||
override fun Bot.addManager(id: Long): Boolean {
|
||||
return ManagersConfig[this].add(id)
|
||||
}
|
||||
}
|
||||
|
||||
public val Bot.managers: List<Long>
|
||||
get() = ManagersConfig[this].toList()
|
||||
|
||||
internal fun Bot.addManager(id: Long): Boolean {
|
||||
return ManagersConfig[this].add(id)
|
||||
}
|
||||
|
||||
|
||||
internal object ManagersConfig : Setting by ConsoleBuiltInSettingStorage.load() {
|
||||
private val managers: MutableMap<Long, MutableSet<Long>> by value()
|
||||
|
@ -12,7 +12,7 @@
|
||||
package net.mamoe.mirai.console.plugin
|
||||
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
|
@ -12,7 +12,7 @@
|
||||
package net.mamoe.mirai.console.plugin
|
||||
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.plugin.jvm.PluginManagerImpl
|
||||
import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
@ -55,7 +55,9 @@ public interface PluginManager {
|
||||
*/
|
||||
public val Plugin.description: PluginDescription
|
||||
|
||||
public companion object INSTANCE : PluginManager by PluginManagerImpl
|
||||
public companion object INSTANCE : PluginManager by PluginManagerImpl {
|
||||
override val Plugin.description: PluginDescription get() = PluginManagerImpl.run { description }
|
||||
}
|
||||
}
|
||||
|
||||
@JvmSynthetic
|
||||
|
@ -11,7 +11,7 @@ package net.mamoe.mirai.console.plugin.center
|
||||
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import java.io.File
|
||||
|
||||
@ConsoleExperimentalAPI
|
||||
|
@ -13,8 +13,8 @@ import com.vdurmont.semver4j.Semver
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.builtins.serializer
|
||||
import net.mamoe.mirai.console.setting.internal.map
|
||||
import net.mamoe.mirai.console.utils.SemverAsStringSerializerIvy
|
||||
import net.mamoe.mirai.console.internal.setting.SemverAsStringSerializerIvy
|
||||
import net.mamoe.mirai.console.internal.setting.map
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
import net.mamoe.yamlkt.YamlDynamicSerializer
|
||||
import java.io.File
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.plugin.jvm
|
||||
|
||||
import net.mamoe.mirai.console.plugin.internal.JvmPluginInternal
|
||||
import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal
|
||||
import net.mamoe.mirai.utils.minutesToSeconds
|
||||
import net.mamoe.mirai.utils.secondsToMillis
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
@ -10,10 +10,10 @@
|
||||
package net.mamoe.mirai.console.plugin.jvm
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import net.mamoe.mirai.console.internal.plugin.JarPluginLoaderImpl
|
||||
import net.mamoe.mirai.console.plugin.FilePluginLoader
|
||||
import net.mamoe.mirai.console.plugin.internal.JarPluginLoaderImpl
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
|
||||
/**
|
||||
* 内建的 Jar (JVM) 插件加载器
|
||||
@ -25,5 +25,9 @@ public interface JarPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, J
|
||||
@ConsoleExperimentalAPI
|
||||
public val settingStorage: SettingStorage
|
||||
|
||||
public companion object INSTANCE : JarPluginLoader by JarPluginLoaderImpl
|
||||
public companion object INSTANCE : JarPluginLoader by JarPluginLoaderImpl {
|
||||
@Suppress("EXTENSION_SHADOWED_BY_MEMBER")
|
||||
override val JvmPlugin.description: JvmPluginDescription
|
||||
get() = JarPluginLoaderImpl.run { description }
|
||||
}
|
||||
}
|
@ -11,7 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.plugin.jvm
|
||||
|
||||
import net.mamoe.mirai.console.utils.JavaPluginScheduler
|
||||
import net.mamoe.mirai.console.util.JavaPluginScheduler
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
|
@ -16,7 +16,7 @@ import net.mamoe.mirai.console.plugin.Plugin
|
||||
import net.mamoe.mirai.console.plugin.PluginFileExtensions
|
||||
import net.mamoe.mirai.console.setting.AutoSaveSettingHolder
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import net.mamoe.mirai.console.utils.ResourceContainer
|
||||
import net.mamoe.mirai.console.util.ResourceContainer
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
@ -13,11 +13,11 @@ import com.vdurmont.semver4j.Semver
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.Transient
|
||||
import net.mamoe.mirai.console.internal.setting.SemverAsStringSerializerLoose
|
||||
import net.mamoe.mirai.console.plugin.FilePluginDescription
|
||||
import net.mamoe.mirai.console.plugin.PluginDependency
|
||||
import net.mamoe.mirai.console.plugin.PluginDescription
|
||||
import net.mamoe.mirai.console.plugin.PluginKind
|
||||
import net.mamoe.mirai.console.utils.SemverAsStringSerializerLoose
|
||||
import java.io.File
|
||||
|
||||
@Serializable
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.plugin.jvm
|
||||
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
|
@ -12,11 +12,11 @@
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.KSerializer
|
||||
import net.mamoe.mirai.console.internal.setting.*
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.plugin.jvm.loadSetting
|
||||
import net.mamoe.mirai.console.setting.internal.*
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import kotlin.internal.LowPriorityInOverloadResolution
|
||||
import kotlin.reflect.KProperty
|
||||
import kotlin.reflect.KType
|
||||
|
@ -13,10 +13,10 @@ package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import net.mamoe.mirai.console.internal.setting.*
|
||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.setting.SettingStorage.Companion.load
|
||||
import net.mamoe.mirai.console.setting.internal.*
|
||||
import java.io.File
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
|
@ -14,9 +14,9 @@ package net.mamoe.mirai.console.setting
|
||||
import kotlinx.serialization.BinaryFormat
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.StringFormat
|
||||
import net.mamoe.mirai.console.setting.internal.map
|
||||
import net.mamoe.mirai.console.setting.internal.setValueBySerializer
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.internal.setting.map
|
||||
import net.mamoe.mirai.console.internal.setting.setValueBySerializer
|
||||
import net.mamoe.mirai.console.util.ConsoleExperimentalAPI
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,25 @@
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
|
||||
package net.mamoe.mirai.console.util
|
||||
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.internal.utils.BotManagerImpl
|
||||
import net.mamoe.mirai.contact.User
|
||||
|
||||
public interface BotManager {
|
||||
/**
|
||||
* 判断此用户是否为 console 管理员
|
||||
*/
|
||||
public val User.isManager: Boolean
|
||||
public val Bot.managers: List<Long>
|
||||
|
||||
public fun Bot.removeManager(id: Long): Boolean
|
||||
public fun Bot.addManager(id: Long): Boolean
|
||||
|
||||
public companion object INSTANCE : BotManager { // kotlin import handler doesn't recognize delegation.
|
||||
override fun Bot.addManager(id: Long): Boolean = BotManagerImpl.run { addManager(id) }
|
||||
override fun Bot.removeManager(id: Long): Boolean = BotManagerImpl.run { removeManager(id) }
|
||||
override val User.isManager: Boolean get() = BotManagerImpl.run { isManager }
|
||||
override val Bot.managers: List<Long> get() = BotManagerImpl.run { managers }
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
|
||||
@file:Suppress("INAPPLICABLE_JVM_NAME", "unused")
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
package net.mamoe.mirai.console.util
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.coroutines.sync.Mutex
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
package net.mamoe.mirai.console.util
|
||||
|
||||
import kotlin.annotation.AnnotationTarget.*
|
||||
|
@ -7,7 +7,7 @@
|
||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||
*/
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
package net.mamoe.mirai.console.util
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.future.future
|
@ -9,11 +9,10 @@
|
||||
|
||||
@file:Suppress("unused")
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
package net.mamoe.mirai.console.util
|
||||
|
||||
import net.mamoe.mirai.console.encodeToString
|
||||
import net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||
import net.mamoe.mirai.console.utils.ResourceContainer.Companion.asResourceContainer
|
||||
import net.mamoe.mirai.console.util.ResourceContainer.Companion.asResourceContainer
|
||||
import java.io.InputStream
|
||||
import java.nio.charset.Charset
|
||||
import kotlin.reflect.KClass
|
||||
@ -42,7 +41,7 @@ public interface ResourceContainer {
|
||||
*/
|
||||
@JvmDefault
|
||||
public fun getResource(name: String, charset: Charset): String =
|
||||
this.getResourceAsStream(name).use { it.readBytes() }.encodeToString(charset)
|
||||
String(this.getResourceAsStream(name).use { it.readBytes() })
|
||||
|
||||
public companion object {
|
||||
/**
|
@ -9,7 +9,7 @@
|
||||
|
||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "RESULT_CLASS_IN_RETURN_TYPE")
|
||||
|
||||
package net.mamoe.mirai.console.utils
|
||||
package net.mamoe.mirai.console.util
|
||||
|
||||
import org.jetbrains.annotations.Range
|
||||
import kotlin.contracts.InvocationKind
|
@ -21,7 +21,7 @@ import net.mamoe.mirai.console.plugin.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||
import net.mamoe.mirai.console.setting.MemorySettingStorage
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.utils.DefaultLogger
|
||||
import net.mamoe.mirai.utils.LoginSolver
|
||||
|
@ -16,11 +16,16 @@ import kotlinx.coroutines.runBlocking
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.Testing
|
||||
import net.mamoe.mirai.console.Testing.withTesting
|
||||
import net.mamoe.mirai.console.command.description.CommandArgParser
|
||||
import net.mamoe.mirai.console.command.description.CommandParserContext
|
||||
import net.mamoe.mirai.console.command.internal.InternalCommandManager
|
||||
import net.mamoe.mirai.console.command.internal.flattenCommandComponents
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.execute
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.registeredCommands
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentContext
|
||||
import net.mamoe.mirai.console.command.description.CommandArgumentParser
|
||||
import net.mamoe.mirai.console.initTestEnvironment
|
||||
import net.mamoe.mirai.console.internal.command.flattenCommandComponents
|
||||
import net.mamoe.mirai.message.data.Image
|
||||
import net.mamoe.mirai.message.data.SingleMessage
|
||||
import net.mamoe.mirai.message.data.toMessage
|
||||
@ -75,8 +80,8 @@ internal class TestCommand {
|
||||
|
||||
assertEquals(1, ConsoleCommandOwner.registeredCommands.size)
|
||||
|
||||
assertEquals(1, InternalCommandManager.registeredCommands.size)
|
||||
assertEquals(2, InternalCommandManager.requiredPrefixCommandMap.size)
|
||||
assertEquals(1, CommandManagerImpl.registeredCommands.size)
|
||||
assertEquals(2, CommandManagerImpl.requiredPrefixCommandMap.size)
|
||||
} finally {
|
||||
TestCompositeCommand.unregister()
|
||||
}
|
||||
@ -180,8 +185,8 @@ internal class TestCommand {
|
||||
val composite = object : CompositeCommand(
|
||||
ConsoleCommandOwner,
|
||||
"test",
|
||||
overrideContext = CommandParserContext {
|
||||
add(object : CommandArgParser<MyClass> {
|
||||
overrideContext = CommandArgumentContext {
|
||||
add(object : CommandArgumentParser<MyClass> {
|
||||
override fun parse(raw: String, sender: CommandSender): MyClass {
|
||||
return MyClass(raw.toInt())
|
||||
}
|
||||
|
@ -9,6 +9,9 @@
|
||||
|
||||
package net.mamoe.mirai.console.command
|
||||
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregister
|
||||
|
||||
inline fun <T : Command, R> T.withRegistration(block: T.() -> R): R {
|
||||
this.register()
|
||||
try {
|
||||
|
@ -10,7 +10,7 @@
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.json.Json
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertSame
|
||||
|
@ -1,6 +1,9 @@
|
||||
@file:Suppress("UnstableApiUsage")
|
||||
plugins {
|
||||
id("com.jfrog.bintray") version Versions.bintray apply false
|
||||
id("net.mamoe.kotlin-jvm-blocking-bridge") version Versions.blockingBridge apply false
|
||||
kotlin("jvm") version Versions.kotlinCompiler
|
||||
kotlin("plugin.serialization") version Versions.kotlinCompiler
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile::class.java) {
|
||||
|
@ -29,9 +29,7 @@ dependencies {
|
||||
api(ktor("client-json", "1.3.2"))
|
||||
|
||||
compileOnly(gradleApi())
|
||||
//compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
|
||||
//runtimeOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.72")
|
||||
compileOnly("org.jetbrains.kotlin:kotlin-gradle-plugin:1.4.0-rc")
|
||||
compileOnly("com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.5")
|
||||
api("com.github.jengelman.gradle.plugins:shadow:6.0.0")
|
||||
}
|
@ -30,7 +30,7 @@ class MiraiConsoleBuildPlugin : Plugin<Project> {
|
||||
tasks.getByName("shadowJar") {
|
||||
with(this as ShadowJar) {
|
||||
archiveFileName.set(
|
||||
"${target.name}-${target.version}.jar"
|
||||
"${target.name}-${target.version}-all.jar"
|
||||
)
|
||||
manifest {
|
||||
attributes(
|
||||
@ -101,7 +101,7 @@ fun Project.findLatestFile(): Map.Entry<String, File> {
|
||||
return File(projectDir, "build/libs").walk()
|
||||
.filter { it.isFile }
|
||||
.onEach { println("all files=$it") }
|
||||
.filter { it.name.matches(Regex("""${project.name}-[0-9][0-9]*(\.[0-9]*)*.*\.jar""")) }
|
||||
.filter { it.name.matches(Regex("""${project.name}-[0-9][0-9]*(\.[0-9]*)*.*\-all\.jar""")) }
|
||||
.onEach { println("matched file: ${it.name}") }
|
||||
.associateBy { it.nameWithoutExtension.substringAfterLast('-') }
|
||||
.onEach { println("versions: $it") }
|
||||
|
@ -34,4 +34,6 @@ object Versions {
|
||||
const val androidGradle = "3.6.2"
|
||||
|
||||
const val bintray = "1.8.5"
|
||||
|
||||
const val blockingBridge = "0.9.0"
|
||||
}
|
@ -1,12 +1,19 @@
|
||||
plugins {
|
||||
kotlin("jvm") version Versions.kotlinCompiler
|
||||
kotlin("plugin.serialization") version Versions.kotlinCompiler
|
||||
kotlin("jvm")
|
||||
kotlin("plugin.serialization")
|
||||
id("java")
|
||||
`maven-publish`
|
||||
id("com.jfrog.bintray")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
target.compilations.all {
|
||||
kotlinOptions {
|
||||
jvmTarget = "1.8"
|
||||
freeCompilerArgs = freeCompilerArgs + "-Xjvm-default=all"
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
all {
|
||||
languageSettings.enableLanguageFeature("InlineClasses")
|
||||
@ -16,7 +23,7 @@ kotlin {
|
||||
languageSettings.progressiveMode = true
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI")
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI")
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.console.utils.ConsoleExperimentalAPI")
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalAPI")
|
||||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.console.ConsoleFrontEndImplementation")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes")
|
||||
languageSettings.useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference")
|
||||
|
@ -25,9 +25,8 @@ package net.mamoe.mirai.console.pure
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.withContext
|
||||
import net.mamoe.mirai.Bot
|
||||
import net.mamoe.mirai.console.MiraiConsoleBuildConstants
|
||||
import net.mamoe.mirai.console.MiraiConsoleFrontEnd
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.utils.DefaultLoginSolver
|
||||
import net.mamoe.mirai.utils.LoginSolver
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
@ -72,13 +71,13 @@ object MiraiConsoleFrontEndPure : MiraiConsoleFrontEnd {
|
||||
const val COLOR_RESET = "\u001b[39;49m"
|
||||
// }
|
||||
|
||||
val sdf by lazy {
|
||||
private val sdf by lazy {
|
||||
SimpleDateFormat("HH:mm:ss")
|
||||
}
|
||||
override val name: String
|
||||
get() = "Pure"
|
||||
override val version: String
|
||||
get() = MiraiConsoleBuildConstants.version
|
||||
get() = net.mamoe.mirai.console.internal.MiraiConsoleBuildConstants.version
|
||||
|
||||
override fun loggerFor(identity: String?): MiraiLogger {
|
||||
identity?.apply {
|
||||
|
@ -34,7 +34,7 @@ import net.mamoe.mirai.console.plugin.PluginLoader
|
||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||
import net.mamoe.mirai.console.setting.MultiFileSettingStorage
|
||||
import net.mamoe.mirai.console.setting.SettingStorage
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.utils.MiraiLogger
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
|
@ -23,8 +23,13 @@ package net.mamoe.mirai.console.pure
|
||||
import kotlinx.coroutines.isActive
|
||||
import net.mamoe.mirai.console.MiraiConsole
|
||||
import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start
|
||||
import net.mamoe.mirai.console.command.*
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.console.command.BuiltInCommands
|
||||
import net.mamoe.mirai.console.command.Command.Companion.primaryName
|
||||
import net.mamoe.mirai.console.command.CommandExecuteStatus
|
||||
import net.mamoe.mirai.console.command.CommandManager
|
||||
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommandDetailed
|
||||
import net.mamoe.mirai.console.command.ConsoleCommandSender
|
||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||
import net.mamoe.mirai.message.data.Message
|
||||
import net.mamoe.mirai.message.data.content
|
||||
import net.mamoe.mirai.utils.DefaultLogger
|
||||
@ -74,11 +79,11 @@ internal fun startConsoleThread() {
|
||||
while (isActive) {
|
||||
val next = MiraiConsoleFrontEndPure.requestInput("").let {
|
||||
when {
|
||||
it.startsWith(CommandPrefix) -> {
|
||||
it.startsWith(CommandManager.commandPrefix) -> {
|
||||
it
|
||||
}
|
||||
it == "?" -> CommandPrefix + BuiltInCommands.Help.primaryName
|
||||
else -> CommandPrefix + it
|
||||
it == "?" -> CommandManager.commandPrefix + BuiltInCommands.Help.primaryName
|
||||
else -> CommandManager.commandPrefix + it
|
||||
}
|
||||
}
|
||||
if (next.isBlank()) {
|
||||
|
Loading…
Reference in New Issue
Block a user