mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-10 18:40:15 +08:00
Explicit APIs
This commit is contained in:
parent
55ec375e09
commit
58187f95f0
@ -7,7 +7,7 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("PRE_RELEASE_CLASS", "ClassName")
|
@file:Suppress("PRE_RELEASE_CLASS", "ClassName", "RedundantVisibilityModifier")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.codegen
|
package net.mamoe.mirai.console.codegen
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ import kotlin.reflect.full.functions
|
|||||||
import kotlin.reflect.full.hasAnnotation
|
import kotlin.reflect.full.hasAnnotation
|
||||||
import kotlin.reflect.full.isSubclassOf
|
import kotlin.reflect.full.isSubclassOf
|
||||||
|
|
||||||
object ValueSettingCodegen {
|
internal object ValueSettingCodegen {
|
||||||
/**
|
/**
|
||||||
* The interface
|
* The interface
|
||||||
*/
|
*/
|
||||||
@ -31,7 +31,7 @@ object ValueSettingCodegen {
|
|||||||
/**
|
/**
|
||||||
* Represents a non-null [$ktType] value.
|
* Represents a non-null [$ktType] value.
|
||||||
*/
|
*/
|
||||||
interface ${ktType}Value : PrimitiveValue<$ktType>
|
public interface ${ktType}Value : PrimitiveValue<$ktType>
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -47,7 +47,7 @@ object ValueSettingCodegen {
|
|||||||
kCode(
|
kCode(
|
||||||
"""
|
"""
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val ${ktType.standardName}SerializerDescriptor = ${ktType.standardName}.serializer().descriptor
|
internal val ${ktType.standardName}SerializerDescriptor = ${ktType.standardName}.serializer().descriptor
|
||||||
"""
|
"""
|
||||||
).lines().joinToString("\n") { " $it" }
|
).lines().joinToString("\n") { " $it" }
|
||||||
)
|
)
|
||||||
@ -145,7 +145,7 @@ internal fun Setting.${ktType.lowerCaseName}ValueImpl(): SerializerAwareValue<${
|
|||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
appendKCode(
|
appendKCode(
|
||||||
"""
|
"""
|
||||||
fun Setting.value(default: ${ktType.standardName}): SerializerAwareValue<${ktType.standardName}> = valueImpl(default)
|
public fun Setting.value(default: ${ktType.standardName}): SerializerAwareValue<${ktType.standardName}> = valueImpl(default)
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,8 @@ tasks.withType(JavaCompile::class.java) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
|
explicitApiWarning()
|
||||||
|
|
||||||
sourceSets.all {
|
sourceSets.all {
|
||||||
target.compilations.all {
|
target.compilations.all {
|
||||||
kotlinOptions {
|
kotlinOptions {
|
||||||
@ -46,12 +48,17 @@ kotlin {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets.invoke {
|
||||||
getByName("test") {
|
getByName("test") {
|
||||||
languageSettings.apply {
|
languageSettings.apply {
|
||||||
languageVersion = "1.4"
|
languageVersion = "1.4"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
getByName("main") {
|
||||||
|
languageSettings.apply {
|
||||||
|
languageVersion = "1.3"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -71,7 +78,7 @@ dependencies {
|
|||||||
testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0")
|
testImplementation("org.junit.jupiter:junit-jupiter-api:5.2.0")
|
||||||
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0")
|
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine:5.2.0")
|
||||||
}
|
}
|
||||||
ext {
|
ext.apply {
|
||||||
// 傻逼 compileAndRuntime 没 exclude 掉
|
// 傻逼 compileAndRuntime 没 exclude 掉
|
||||||
// 傻逼 gradle 第二次配置 task 会覆盖掉第一次的配置
|
// 傻逼 gradle 第二次配置 task 会覆盖掉第一次的配置
|
||||||
val x: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.() -> Unit = {
|
val x: com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar.() -> Unit = {
|
||||||
@ -83,7 +90,7 @@ ext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.set("shadowJar", x)
|
set("shadowJar", x)
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks {
|
tasks {
|
||||||
|
@ -23,6 +23,7 @@ import net.mamoe.mirai.console.command.internal.InternalCommandManager
|
|||||||
import net.mamoe.mirai.console.command.primaryName
|
import net.mamoe.mirai.console.command.primaryName
|
||||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||||
import net.mamoe.mirai.console.plugin.PluginManager
|
import net.mamoe.mirai.console.plugin.PluginManager
|
||||||
|
import net.mamoe.mirai.console.plugin.PluginManagerImpl
|
||||||
import net.mamoe.mirai.console.plugin.center.CuiPluginCenter
|
import net.mamoe.mirai.console.plugin.center.CuiPluginCenter
|
||||||
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
||||||
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader
|
||||||
@ -45,43 +46,47 @@ import kotlin.coroutines.CoroutineContext
|
|||||||
*
|
*
|
||||||
* @see INSTANCE
|
* @see INSTANCE
|
||||||
*/
|
*/
|
||||||
interface MiraiConsole : CoroutineScope {
|
public interface MiraiConsole : CoroutineScope {
|
||||||
/**
|
/**
|
||||||
* Console 运行路径
|
* Console 运行路径
|
||||||
*/
|
*/
|
||||||
val rootDir: File
|
public val rootDir: File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Console 前端接口
|
* Console 前端接口
|
||||||
*/
|
*/
|
||||||
val frontEnd: MiraiConsoleFrontEnd
|
public val frontEnd: MiraiConsoleFrontEnd
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 与前端交互所使用的 Logger
|
* 与前端交互所使用的 Logger
|
||||||
*/
|
*/
|
||||||
val mainLogger: MiraiLogger
|
public val mainLogger: MiraiLogger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内建加载器列表, 一般需要包含 [JarPluginLoader]
|
* 内建加载器列表, 一般需要包含 [JarPluginLoader]
|
||||||
*/
|
*/
|
||||||
val builtInPluginLoaders: List<PluginLoader<*, *>>
|
public val builtInPluginLoaders: List<PluginLoader<*, *>>
|
||||||
|
|
||||||
val buildDate: Date
|
public val buildDate: Date
|
||||||
|
|
||||||
val version: String
|
public val version: String
|
||||||
|
|
||||||
val pluginCenter: PluginCenter
|
public val pluginCenter: PluginCenter
|
||||||
|
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
fun newLogger(identity: String?): MiraiLogger
|
public fun newLogger(identity: String?): MiraiLogger
|
||||||
|
|
||||||
companion object INSTANCE : MiraiConsole by MiraiConsoleInternal
|
public companion object INSTANCE : MiraiConsole by MiraiConsoleInternal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class IllegalMiraiConsoleImplementationError(
|
||||||
|
override val message: String?
|
||||||
|
) : Error()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取 [MiraiConsole] 的 [Job]
|
* 获取 [MiraiConsole] 的 [Job]
|
||||||
*/
|
*/
|
||||||
val MiraiConsole.job: Job
|
public val MiraiConsole.job: Job
|
||||||
get() = this.coroutineContext[Job] ?: error("Internal error: Job not found in MiraiConsole.coroutineContext")
|
get() = this.coroutineContext[Job] ?: error("Internal error: Job not found in MiraiConsole.coroutineContext")
|
||||||
|
|
||||||
//// internal
|
//// internal
|
||||||
@ -149,17 +154,13 @@ internal object MiraiConsoleInternal : CoroutineScope, IMiraiConsole, MiraiConso
|
|||||||
InternalCommandManager.commandListener // start
|
InternalCommandManager.commandListener // start
|
||||||
|
|
||||||
mainLogger.info { "Loading plugins..." }
|
mainLogger.info { "Loading plugins..." }
|
||||||
PluginManager.loadEnablePlugins()
|
PluginManagerImpl.loadEnablePlugins()
|
||||||
mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." }
|
mainLogger.info { "${PluginManager.plugins.size} plugin(s) loaded." }
|
||||||
mainLogger.info { "mirai-console started successfully." }
|
mainLogger.info { "mirai-console started successfully." }
|
||||||
// Only for initialize
|
// Only for initialize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class IllegalMiraiConsoleImplementationError(
|
|
||||||
override val message: String?
|
|
||||||
) : Error()
|
|
||||||
|
|
||||||
|
|
||||||
// 前端使用
|
// 前端使用
|
||||||
internal interface IMiraiConsole : CoroutineScope {
|
internal interface IMiraiConsole : CoroutineScope {
|
||||||
|
@ -17,33 +17,33 @@ import net.mamoe.mirai.utils.MiraiLogger
|
|||||||
* 只需要实现一个这个传入 MiraiConsole 就可以绑定 UI 层与 Console 层
|
* 只需要实现一个这个传入 MiraiConsole 就可以绑定 UI 层与 Console 层
|
||||||
* 需要保证线程安全
|
* 需要保证线程安全
|
||||||
*/
|
*/
|
||||||
interface MiraiConsoleFrontEnd {
|
public interface MiraiConsoleFrontEnd {
|
||||||
/**
|
/**
|
||||||
* 名称
|
* 名称
|
||||||
*/
|
*/
|
||||||
val name: String
|
public val name: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 版本
|
* 版本
|
||||||
*/
|
*/
|
||||||
val version: String
|
public val version: String
|
||||||
|
|
||||||
fun loggerFor(identity: String?): MiraiLogger
|
public fun loggerFor(identity: String?): MiraiLogger
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 让 UI 层接受一个新的bot
|
* 让 UI 层接受一个新的bot
|
||||||
* */
|
* */
|
||||||
fun pushBot(
|
public fun pushBot(
|
||||||
bot: Bot
|
bot: Bot
|
||||||
)
|
)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 让 UI 层提供一个输入, 相当于 [readLine]
|
* 让 UI 层提供一个输入, 相当于 [readLine]
|
||||||
*/
|
*/
|
||||||
suspend fun requestInput(hint: String): String
|
public suspend fun requestInput(hint: String): String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 由 UI 层创建一个 [LoginSolver]
|
* 由 UI 层创建一个 [LoginSolver]
|
||||||
*/
|
*/
|
||||||
fun createLoginSolver(): LoginSolver
|
public fun createLoginSolver(): LoginSolver
|
||||||
}
|
}
|
@ -29,7 +29,7 @@ import kotlin.system.exitProcess
|
|||||||
/**
|
/**
|
||||||
* 添加一个 [Bot] 实例到全局 Bot 列表, 但不登录.
|
* 添加一个 [Bot] 实例到全局 Bot 列表, 但不登录.
|
||||||
*/
|
*/
|
||||||
fun MiraiConsole.addBot(id: Long, password: String): Bot {
|
public fun MiraiConsole.addBot(id: Long, password: String): Bot {
|
||||||
return Bot(id, password) {
|
return Bot(id, password) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,15 +65,15 @@ fun MiraiConsole.addBot(id: Long, password: String): Bot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("EXPOSED_SUPER_INTERFACE")
|
@Suppress("EXPOSED_SUPER_INTERFACE")
|
||||||
interface BuiltInCommand : Command, BuiltInCommandInternal
|
public interface BuiltInCommand : Command, BuiltInCommandInternal
|
||||||
|
|
||||||
// for identification
|
// for identification
|
||||||
internal interface BuiltInCommandInternal : Command
|
internal interface BuiltInCommandInternal : Command
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
object BuiltInCommands {
|
public object BuiltInCommands {
|
||||||
|
|
||||||
val all: Array<out Command> by lazy {
|
public val all: Array<out Command> by lazy {
|
||||||
this::class.nestedClasses.mapNotNull { it.objectInstance as? Command }.toTypedArray()
|
this::class.nestedClasses.mapNotNull { it.objectInstance as? Command }.toTypedArray()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,7 +83,7 @@ object BuiltInCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Help : SimpleCommand(
|
public object Help : SimpleCommand(
|
||||||
ConsoleCommandOwner, "help",
|
ConsoleCommandOwner, "help",
|
||||||
description = "Gets help about the console."
|
description = "Gets help about the console."
|
||||||
), BuiltInCommand {
|
), BuiltInCommand {
|
||||||
@ -94,13 +94,13 @@ object BuiltInCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Handler
|
@Handler
|
||||||
suspend fun CommandSender.handle() {
|
public suspend fun CommandSender.handle() {
|
||||||
sendMessage("现在有指令: ${allRegisteredCommands.joinToString { it.primaryName }}")
|
sendMessage("现在有指令: ${allRegisteredCommands.joinToString { it.primaryName }}")
|
||||||
sendMessage("帮助还没写, 将就一下")
|
sendMessage("帮助还没写, 将就一下")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Stop : SimpleCommand(
|
public object Stop : SimpleCommand(
|
||||||
ConsoleCommandOwner, "stop", "shutdown", "exit",
|
ConsoleCommandOwner, "stop", "shutdown", "exit",
|
||||||
description = "Stop the whole world."
|
description = "Stop the whole world."
|
||||||
), BuiltInCommand {
|
), BuiltInCommand {
|
||||||
@ -116,7 +116,7 @@ object BuiltInCommands {
|
|||||||
private val closingLock = Mutex()
|
private val closingLock = Mutex()
|
||||||
|
|
||||||
@Handler
|
@Handler
|
||||||
suspend fun CommandSender.handle(): Unit = closingLock.withLock {
|
public suspend fun CommandSender.handle(): Unit = closingLock.withLock {
|
||||||
sendMessage("Stopping mirai-console")
|
sendMessage("Stopping mirai-console")
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
MiraiConsole.job.cancelAndJoin()
|
MiraiConsole.job.cancelAndJoin()
|
||||||
@ -131,27 +131,28 @@ object BuiltInCommands {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object Login : SimpleCommand(
|
public object Login : SimpleCommand(
|
||||||
ConsoleCommandOwner, "login",
|
ConsoleCommandOwner, "login",
|
||||||
description = "Log in a bot account."
|
description = "Log in a bot account."
|
||||||
), BuiltInCommand {
|
), BuiltInCommand {
|
||||||
@Handler
|
@Handler
|
||||||
suspend fun CommandSender.handle(id: Long, password: String) {
|
public suspend fun CommandSender.handle(id: Long, password: String) {
|
||||||
|
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
MiraiConsole.addBot(id, password).alsoLogin()
|
MiraiConsole.addBot(id, password).alsoLogin()
|
||||||
}.fold(
|
}.fold(
|
||||||
onSuccess = { sendMessage("${it.nick} ($id) Login succeed") },
|
onSuccess = { sendMessage("${it.nick} ($id) Login succeed") },
|
||||||
onFailure = { throwable ->
|
onFailure = { throwable ->
|
||||||
sendMessage("Login failed: ${throwable.localizedMessage ?: throwable.message ?: throwable.toString()}" +
|
sendMessage(
|
||||||
if (this is MessageEventContextAware<*>) {
|
"Login failed: ${throwable.localizedMessage ?: throwable.message ?: throwable.toString()}" +
|
||||||
this.fromEvent.selectMessagesUnit {
|
if (this is MessageEventContextAware<*>) {
|
||||||
"stacktrace" reply {
|
this.fromEvent.selectMessagesUnit {
|
||||||
throwable.stacktraceString
|
"stacktrace" reply {
|
||||||
|
throwable.stacktraceString
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
"test"
|
||||||
"test"
|
} else "")
|
||||||
} else "")
|
|
||||||
|
|
||||||
throw throwable
|
throw throwable
|
||||||
}
|
}
|
||||||
|
@ -22,55 +22,58 @@ import net.mamoe.mirai.message.data.SingleMessage
|
|||||||
* @see RawCommand
|
* @see RawCommand
|
||||||
* @see CompositeCommand
|
* @see CompositeCommand
|
||||||
*/
|
*/
|
||||||
interface Command {
|
public interface Command {
|
||||||
/**
|
/**
|
||||||
* 指令名. 需要至少有一个元素. 所有元素都不能带有空格
|
* 指令名. 需要至少有一个元素. 所有元素都不能带有空格
|
||||||
*/
|
*/
|
||||||
val names: Array<out String>
|
public val names: Array<out String>
|
||||||
|
|
||||||
val usage: String
|
public val usage: String
|
||||||
|
|
||||||
val description: String
|
public val description: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令权限
|
* 指令权限
|
||||||
*/
|
*/
|
||||||
val permission: CommandPermission
|
public val permission: CommandPermission
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 为 `true` 时表示 [指令前缀][CommandPrefix] 可选
|
* 为 `true` 时表示 [指令前缀][CommandPrefix] 可选
|
||||||
*/
|
*/
|
||||||
val prefixOptional: Boolean
|
public val prefixOptional: Boolean
|
||||||
|
|
||||||
val owner: CommandOwner
|
public val owner: CommandOwner
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param args 指令参数. 可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割.
|
* @param args 指令参数. 可能是 [SingleMessage] 或 [String]. 且已经以 ' ' 分割.
|
||||||
|
*
|
||||||
|
* @see Command.execute
|
||||||
*/ // TODO: 2020/6/28 Java-friendly bridges
|
*/ // TODO: 2020/6/28 Java-friendly bridges
|
||||||
suspend fun CommandSender.onCommand(args: Array<out Any>)
|
public suspend fun CommandSender.onCommand(args: Array<out Any>)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [Command] 的基础实现
|
* [Command] 的基础实现
|
||||||
*/
|
*/
|
||||||
abstract class AbstractCommand @JvmOverloads constructor(
|
public abstract class AbstractCommand @JvmOverloads constructor(
|
||||||
final override val owner: CommandOwner,
|
public final override val owner: CommandOwner,
|
||||||
vararg names: String,
|
vararg names: String,
|
||||||
description: String = "<no description available>",
|
description: String = "<no description available>",
|
||||||
final override val permission: CommandPermission = CommandPermission.Default,
|
public final override val permission: CommandPermission = CommandPermission.Default,
|
||||||
final override val prefixOptional: Boolean = false
|
public final override val prefixOptional: Boolean = false
|
||||||
) : Command {
|
) : Command {
|
||||||
final override val description = description.trimIndent()
|
public final override val description: String = description.trimIndent()
|
||||||
final override val names: Array<out String> =
|
public final override val names: Array<out String> =
|
||||||
names.map(String::trim).filterNot(String::isEmpty).map(String::toLowerCase).also { list ->
|
names.map(String::trim).filterNot(String::isEmpty).map(String::toLowerCase).also { list ->
|
||||||
list.firstOrNull { !it.isValidSubName() }?.let { error("Invalid name: $it") }
|
list.firstOrNull { !it.isValidSubName() }?.let { error("Invalid name: $it") }
|
||||||
}.toTypedArray()
|
}.toTypedArray()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun Command.onCommand(sender: CommandSender, args: Array<out Any>) = sender.run { onCommand(args) }
|
public suspend inline fun Command.onCommand(sender: CommandSender, args: Array<out Any>): Unit =
|
||||||
|
sender.run { onCommand(args) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 主要指令名. 为 [Command.names] 的第一个元素.
|
* 主要指令名. 为 [Command.names] 的第一个元素.
|
||||||
*/
|
*/
|
||||||
val Command.primaryName: String get() = names[0]
|
public val Command.primaryName: String get() = names[0]
|
@ -20,94 +20,94 @@ import kotlin.contracts.contract
|
|||||||
*
|
*
|
||||||
* @see CommandExecuteStatus
|
* @see CommandExecuteStatus
|
||||||
*/
|
*/
|
||||||
sealed class CommandExecuteResult {
|
public sealed class CommandExecuteResult {
|
||||||
/** 指令最终执行状态 */
|
/** 指令最终执行状态 */
|
||||||
abstract val status: CommandExecuteStatus
|
public abstract val status: CommandExecuteStatus
|
||||||
|
|
||||||
/** 指令执行时发生的错误 (如果有) */
|
/** 指令执行时发生的错误 (如果有) */
|
||||||
abstract val exception: Throwable?
|
public abstract val exception: Throwable?
|
||||||
|
|
||||||
/** 尝试执行的指令 (如果匹配到) */
|
/** 尝试执行的指令 (如果匹配到) */
|
||||||
abstract val command: Command?
|
public abstract val command: Command?
|
||||||
|
|
||||||
/** 尝试执行的指令名 (如果匹配到) */
|
/** 尝试执行的指令名 (如果匹配到) */
|
||||||
abstract val commandName: String?
|
public abstract val commandName: String?
|
||||||
|
|
||||||
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
abstract val args: Array<out Any>?
|
public abstract val args: Array<out Any>?
|
||||||
|
|
||||||
// abstract val to allow smart casting
|
// abstract val to allow smart casting
|
||||||
|
|
||||||
/** 指令执行成功 */
|
/** 指令执行成功 */
|
||||||
class Success(
|
public class Success(
|
||||||
/** 尝试执行的指令 */
|
/** 尝试执行的指令 */
|
||||||
override val command: Command,
|
public override val command: Command,
|
||||||
/** 尝试执行的指令名 */
|
/** 尝试执行的指令名 */
|
||||||
override val commandName: String,
|
public override val commandName: String,
|
||||||
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
override val args: Array<out Any>
|
public override val args: Array<out Any>
|
||||||
) : CommandExecuteResult() {
|
) : CommandExecuteResult() {
|
||||||
/** 指令执行时发生的错误, 总是 `null` */
|
/** 指令执行时发生的错误, 总是 `null` */
|
||||||
override val exception: Nothing? get() = null
|
public override val exception: Nothing? get() = null
|
||||||
|
|
||||||
/** 指令最终执行状态, 总是 [CommandExecuteStatus.SUCCESSFUL] */
|
/** 指令最终执行状态, 总是 [CommandExecuteStatus.SUCCESSFUL] */
|
||||||
override val status: CommandExecuteStatus get() = CommandExecuteStatus.SUCCESSFUL
|
public override val status: CommandExecuteStatus get() = CommandExecuteStatus.SUCCESSFUL
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 指令执行过程出现了错误 */
|
/** 指令执行过程出现了错误 */
|
||||||
class ExecutionException(
|
public class ExecutionException(
|
||||||
/** 指令执行时发生的错误 */
|
/** 指令执行时发生的错误 */
|
||||||
override val exception: Throwable,
|
public override val exception: Throwable,
|
||||||
/** 尝试执行的指令 */
|
/** 尝试执行的指令 */
|
||||||
override val command: Command,
|
public override val command: Command,
|
||||||
/** 尝试执行的指令名 */
|
/** 尝试执行的指令名 */
|
||||||
override val commandName: String,
|
public override val commandName: String,
|
||||||
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
override val args: Array<out Any>
|
public override val args: Array<out Any>
|
||||||
) : CommandExecuteResult() {
|
) : CommandExecuteResult() {
|
||||||
/** 指令最终执行状态, 总是 [CommandExecuteStatus.EXECUTION_EXCEPTION] */
|
/** 指令最终执行状态, 总是 [CommandExecuteStatus.EXECUTION_EXCEPTION] */
|
||||||
override val status: CommandExecuteStatus get() = CommandExecuteStatus.EXECUTION_EXCEPTION
|
public override val status: CommandExecuteStatus get() = CommandExecuteStatus.EXECUTION_EXCEPTION
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 没有匹配的指令 */
|
/** 没有匹配的指令 */
|
||||||
class CommandNotFound(
|
public class CommandNotFound(
|
||||||
/** 尝试执行的指令名 */
|
/** 尝试执行的指令名 */
|
||||||
override val commandName: String
|
public override val commandName: String
|
||||||
) : CommandExecuteResult() {
|
) : CommandExecuteResult() {
|
||||||
/** 指令执行时发生的错误, 总是 `null` */
|
/** 指令执行时发生的错误, 总是 `null` */
|
||||||
override val exception: Nothing? get() = null
|
public override val exception: Nothing? get() = null
|
||||||
|
|
||||||
/** 尝试执行的指令, 总是 `null` */
|
/** 尝试执行的指令, 总是 `null` */
|
||||||
override val command: Nothing? get() = null
|
public override val command: Nothing? get() = null
|
||||||
|
|
||||||
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
override val args: Nothing? get() = null
|
public override val args: Nothing? get() = null
|
||||||
|
|
||||||
/** 指令最终执行状态, 总是 [CommandExecuteStatus.COMMAND_NOT_FOUND] */
|
/** 指令最终执行状态, 总是 [CommandExecuteStatus.COMMAND_NOT_FOUND] */
|
||||||
override val status: CommandExecuteStatus get() = CommandExecuteStatus.COMMAND_NOT_FOUND
|
public override val status: CommandExecuteStatus get() = CommandExecuteStatus.COMMAND_NOT_FOUND
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 权限不足 */
|
/** 权限不足 */
|
||||||
class PermissionDenied(
|
public class PermissionDenied(
|
||||||
/** 尝试执行的指令 */
|
/** 尝试执行的指令 */
|
||||||
override val command: Command,
|
public override val command: Command,
|
||||||
/** 尝试执行的指令名 */
|
/** 尝试执行的指令名 */
|
||||||
override val commandName: String
|
public override val commandName: String
|
||||||
) : CommandExecuteResult() {
|
) : CommandExecuteResult() {
|
||||||
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
/** 基础分割后的实际参数列表, 元素类型可能为 [Message] 或 [String] */
|
||||||
override val args: Nothing? get() = null
|
public override val args: Nothing? get() = null
|
||||||
|
|
||||||
/** 指令执行时发生的错误, 总是 `null` */
|
/** 指令执行时发生的错误, 总是 `null` */
|
||||||
override val exception: Nothing? get() = null
|
public override val exception: Nothing? get() = null
|
||||||
|
|
||||||
/** 指令最终执行状态, 总是 [CommandExecuteStatus.PERMISSION_DENIED] */
|
/** 指令最终执行状态, 总是 [CommandExecuteStatus.PERMISSION_DENIED] */
|
||||||
override val status: CommandExecuteStatus get() = CommandExecuteStatus.PERMISSION_DENIED
|
public override val status: CommandExecuteStatus get() = CommandExecuteStatus.PERMISSION_DENIED
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令的执行状态
|
* 指令的执行状态
|
||||||
*/
|
*/
|
||||||
enum class CommandExecuteStatus {
|
public enum class CommandExecuteStatus {
|
||||||
/** 指令执行成功 */
|
/** 指令执行成功 */
|
||||||
SUCCESSFUL,
|
SUCCESSFUL,
|
||||||
|
|
||||||
@ -124,13 +124,13 @@ sealed class CommandExecuteResult {
|
|||||||
|
|
||||||
|
|
||||||
@Suppress("RemoveRedundantQualifierName")
|
@Suppress("RemoveRedundantQualifierName")
|
||||||
typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus
|
public typealias CommandExecuteStatus = CommandExecuteResult.CommandExecuteStatus
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 当 [this] 为 [CommandExecuteResult.Success] 时返回 `true`
|
* 当 [this] 为 [CommandExecuteResult.Success] 时返回 `true`
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
fun CommandExecuteResult.isSuccess(): Boolean {
|
public fun CommandExecuteResult.isSuccess(): Boolean {
|
||||||
contract {
|
contract {
|
||||||
returns(true) implies (this@isSuccess is CommandExecuteResult.Success)
|
returns(true) implies (this@isSuccess is CommandExecuteResult.Success)
|
||||||
returns(false) implies (this@isSuccess !is CommandExecuteResult.Success)
|
returns(false) implies (this@isSuccess !is CommandExecuteResult.Success)
|
||||||
@ -142,7 +142,7 @@ fun CommandExecuteResult.isSuccess(): Boolean {
|
|||||||
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
fun CommandExecuteResult.isExecutionException(): Boolean {
|
public fun CommandExecuteResult.isExecutionException(): Boolean {
|
||||||
contract {
|
contract {
|
||||||
returns(true) implies (this@isExecutionException is CommandExecuteResult.ExecutionException)
|
returns(true) implies (this@isExecutionException is CommandExecuteResult.ExecutionException)
|
||||||
returns(false) implies (this@isExecutionException !is CommandExecuteResult.ExecutionException)
|
returns(false) implies (this@isExecutionException !is CommandExecuteResult.ExecutionException)
|
||||||
@ -154,7 +154,7 @@ fun CommandExecuteResult.isExecutionException(): Boolean {
|
|||||||
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
fun CommandExecuteResult.isPermissionDenied(): Boolean {
|
public fun CommandExecuteResult.isPermissionDenied(): Boolean {
|
||||||
contract {
|
contract {
|
||||||
returns(true) implies (this@isPermissionDenied is CommandExecuteResult.PermissionDenied)
|
returns(true) implies (this@isPermissionDenied is CommandExecuteResult.PermissionDenied)
|
||||||
returns(false) implies (this@isPermissionDenied !is CommandExecuteResult.PermissionDenied)
|
returns(false) implies (this@isPermissionDenied !is CommandExecuteResult.PermissionDenied)
|
||||||
@ -166,7 +166,7 @@ fun CommandExecuteResult.isPermissionDenied(): Boolean {
|
|||||||
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 时返回 `true`
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
fun CommandExecuteResult.isCommandNotFound(): Boolean {
|
public fun CommandExecuteResult.isCommandNotFound(): Boolean {
|
||||||
contract {
|
contract {
|
||||||
returns(true) implies (this@isCommandNotFound is CommandExecuteResult.CommandNotFound)
|
returns(true) implies (this@isCommandNotFound is CommandExecuteResult.CommandNotFound)
|
||||||
returns(false) implies (this@isCommandNotFound !is CommandExecuteResult.CommandNotFound)
|
returns(false) implies (this@isCommandNotFound !is CommandExecuteResult.CommandNotFound)
|
||||||
@ -178,7 +178,7 @@ fun CommandExecuteResult.isCommandNotFound(): Boolean {
|
|||||||
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 或 [CommandExecuteResult.CommandNotFound] 时返回 `true`
|
* 当 [this] 为 [CommandExecuteResult.ExecutionException] 或 [CommandExecuteResult.CommandNotFound] 时返回 `true`
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
fun CommandExecuteResult.isFailure(): Boolean {
|
public fun CommandExecuteResult.isFailure(): Boolean {
|
||||||
contract {
|
contract {
|
||||||
returns(true) implies (this@isFailure !is CommandExecuteResult.Success)
|
returns(true) implies (this@isFailure !is CommandExecuteResult.Success)
|
||||||
returns(false) implies (this@isFailure is CommandExecuteResult.Success)
|
returns(false) implies (this@isFailure is CommandExecuteResult.Success)
|
||||||
|
@ -14,21 +14,21 @@ package net.mamoe.mirai.console.command
|
|||||||
/**
|
/**
|
||||||
* 在 [executeCommand] 中, [Command.onCommand] 抛出异常时包装的异常.
|
* 在 [executeCommand] 中, [Command.onCommand] 抛出异常时包装的异常.
|
||||||
*/
|
*/
|
||||||
class CommandExecutionException(
|
public class CommandExecutionException(
|
||||||
/**
|
/**
|
||||||
* 执行过程发生异常的指令
|
* 执行过程发生异常的指令
|
||||||
*/
|
*/
|
||||||
val command: Command,
|
public val command: Command,
|
||||||
/**
|
/**
|
||||||
* 匹配到的指令名
|
* 匹配到的指令名
|
||||||
*/
|
*/
|
||||||
val name: String,
|
public val name: String,
|
||||||
cause: Throwable
|
cause: Throwable
|
||||||
) : RuntimeException(
|
) : RuntimeException(
|
||||||
"Exception while executing command '${command.primaryName}'",
|
"Exception while executing command '${command.primaryName}'",
|
||||||
cause
|
cause
|
||||||
) {
|
) {
|
||||||
override fun toString(): String =
|
public override fun toString(): String =
|
||||||
"CommandExecutionException(command=$command, name='$name')"
|
"CommandExecutionException(command=$command, name='$name')"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,12 +27,12 @@ import net.mamoe.mirai.message.data.MessageChain
|
|||||||
* 指令的所有者.
|
* 指令的所有者.
|
||||||
* @see PluginCommandOwner
|
* @see PluginCommandOwner
|
||||||
*/
|
*/
|
||||||
sealed class CommandOwner
|
public sealed class CommandOwner
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件指令所有者. 插件只能通过 [PluginCommandOwner] 管理指令.
|
* 插件指令所有者. 插件只能通过 [PluginCommandOwner] 管理指令.
|
||||||
*/
|
*/
|
||||||
abstract class PluginCommandOwner(val plugin: Plugin) : CommandOwner() {
|
public abstract class PluginCommandOwner(public val plugin: Plugin) : CommandOwner() {
|
||||||
init {
|
init {
|
||||||
if (plugin is CoroutineScope) { // JVM Plugin
|
if (plugin is CoroutineScope) { // JVM Plugin
|
||||||
plugin.coroutineContext[Job]?.invokeOnCompletion {
|
plugin.coroutineContext[Job]?.invokeOnCompletion {
|
||||||
@ -45,33 +45,33 @@ abstract class PluginCommandOwner(val plugin: Plugin) : CommandOwner() {
|
|||||||
/**
|
/**
|
||||||
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
|
* 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner].
|
||||||
*/
|
*/
|
||||||
object ConsoleCommandOwner : CommandOwner()
|
public object ConsoleCommandOwner : CommandOwner()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取已经注册了的属于这个 [CommandOwner] 的指令列表.
|
* 获取已经注册了的属于这个 [CommandOwner] 的指令列表.
|
||||||
* @see JCommandManager.getRegisteredCommands Java 方法
|
* @see JCommandManager.getRegisteredCommands Java 方法
|
||||||
*/
|
*/
|
||||||
val CommandOwner.registeredCommands: List<Command> get() = InternalCommandManager.registeredCommands.filter { it.owner == this }
|
public val CommandOwner.registeredCommands: List<Command> get() = InternalCommandManager.registeredCommands.filter { it.owner == this }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取所有已经注册了指令列表.
|
* 获取所有已经注册了指令列表.
|
||||||
* @see JCommandManager.getRegisteredCommands Java 方法
|
* @see JCommandManager.getRegisteredCommands Java 方法
|
||||||
*/
|
*/
|
||||||
val allRegisteredCommands: List<Command> get() = InternalCommandManager.registeredCommands.toList() // copy
|
public val allRegisteredCommands: List<Command> get() = InternalCommandManager.registeredCommands.toList() // copy
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 指令前缀, 如 '/'
|
* 指令前缀, 如 '/'
|
||||||
* @see JCommandManager.getCommandPrefix Java 方法
|
* @see JCommandManager.getCommandPrefix Java 方法
|
||||||
*/
|
*/
|
||||||
@get:JvmName("getCommandPrefix")
|
@get:JvmName("getCommandPrefix")
|
||||||
val CommandPrefix: String
|
public val CommandPrefix: String
|
||||||
get() = InternalCommandManager.COMMAND_PREFIX
|
get() = InternalCommandManager.COMMAND_PREFIX
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消注册所有属于 [this] 的指令
|
* 取消注册所有属于 [this] 的指令
|
||||||
* @see JCommandManager.unregisterAllCommands Java 方法
|
* @see JCommandManager.unregisterAllCommands Java 方法
|
||||||
*/
|
*/
|
||||||
fun CommandOwner.unregisterAllCommands() {
|
public fun CommandOwner.unregisterAllCommands() {
|
||||||
for (registeredCommand in registeredCommands) {
|
for (registeredCommand in registeredCommands) {
|
||||||
registeredCommand.unregister()
|
registeredCommand.unregister()
|
||||||
}
|
}
|
||||||
@ -94,7 +94,7 @@ fun CommandOwner.unregisterAllCommands() {
|
|||||||
* @see JCommandManager.register Java 方法
|
* @see JCommandManager.register Java 方法
|
||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun Command.register(override: Boolean = false): Boolean {
|
public fun Command.register(override: Boolean = false): Boolean {
|
||||||
if (this is CompositeCommand) this.subCommands // init
|
if (this is CompositeCommand) this.subCommands // init
|
||||||
|
|
||||||
InternalCommandManager.modifyLock.withLock {
|
InternalCommandManager.modifyLock.withLock {
|
||||||
@ -124,7 +124,7 @@ fun Command.register(override: Boolean = false): Boolean {
|
|||||||
*
|
*
|
||||||
* @see JCommandManager.findDuplicate Java 方法
|
* @see JCommandManager.findDuplicate Java 方法
|
||||||
*/
|
*/
|
||||||
fun Command.findDuplicate(): Command? =
|
public fun Command.findDuplicate(): Command? =
|
||||||
InternalCommandManager.registeredCommands.firstOrNull { it.names intersectsIgnoringCase this.names }
|
InternalCommandManager.registeredCommands.firstOrNull { it.names intersectsIgnoringCase this.names }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -132,7 +132,7 @@ fun Command.findDuplicate(): Command? =
|
|||||||
*
|
*
|
||||||
* @see JCommandManager.unregister Java 方法
|
* @see JCommandManager.unregister Java 方法
|
||||||
*/
|
*/
|
||||||
fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock {
|
public fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock {
|
||||||
if (this.prefixOptional) {
|
if (this.prefixOptional) {
|
||||||
this.names.forEach {
|
this.names.forEach {
|
||||||
InternalCommandManager.optionalPrefixCommandMap.remove(it)
|
InternalCommandManager.optionalPrefixCommandMap.remove(it)
|
||||||
@ -147,7 +147,7 @@ fun Command.unregister(): Boolean = InternalCommandManager.modifyLock.withLock {
|
|||||||
/**
|
/**
|
||||||
* 当 [this] 已经 [注册][register] 后返回 `true`
|
* 当 [this] 已经 [注册][register] 后返回 `true`
|
||||||
*/
|
*/
|
||||||
fun Command.isRegistered(): Boolean = this in InternalCommandManager.registeredCommands
|
public fun Command.isRegistered(): Boolean = this in InternalCommandManager.registeredCommands
|
||||||
|
|
||||||
//// executing without detailed result (faster)
|
//// executing without detailed result (faster)
|
||||||
|
|
||||||
@ -161,7 +161,7 @@ fun Command.isRegistered(): Boolean = this in InternalCommandManager.registeredC
|
|||||||
*
|
*
|
||||||
* @see JCommandManager.executeCommand Java 方法
|
* @see JCommandManager.executeCommand Java 方法
|
||||||
*/
|
*/
|
||||||
suspend fun CommandSender.executeCommand(vararg messages: Any): Command? {
|
public suspend fun CommandSender.executeCommand(vararg messages: Any): Command? {
|
||||||
if (messages.isEmpty()) return null
|
if (messages.isEmpty()) return null
|
||||||
return matchAndExecuteCommandInternal(messages, messages[0].toString().substringBefore(' '))
|
return matchAndExecuteCommandInternal(messages, messages[0].toString().substringBefore(' '))
|
||||||
}
|
}
|
||||||
@ -175,7 +175,7 @@ suspend fun CommandSender.executeCommand(vararg messages: Any): Command? {
|
|||||||
* @see JCommandManager.executeCommand Java 方法
|
* @see JCommandManager.executeCommand Java 方法
|
||||||
*/
|
*/
|
||||||
@Throws(CommandExecutionException::class)
|
@Throws(CommandExecutionException::class)
|
||||||
suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
public suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
||||||
if (message.isEmpty()) return null
|
if (message.isEmpty()) return null
|
||||||
return matchAndExecuteCommandInternal(message, message[0].toString().substringBefore(' '))
|
return matchAndExecuteCommandInternal(message, message[0].toString().substringBefore(' '))
|
||||||
}
|
}
|
||||||
@ -190,7 +190,7 @@ suspend fun CommandSender.executeCommand(message: MessageChain): Command? {
|
|||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@Throws(CommandExecutionException::class)
|
@Throws(CommandExecutionException::class)
|
||||||
suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean = true) {
|
public suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPermission: Boolean = true) {
|
||||||
sender.executeCommandInternal(
|
sender.executeCommandInternal(
|
||||||
this,
|
this,
|
||||||
args.flattenCommandComponents().toTypedArray(),
|
args.flattenCommandComponents().toTypedArray(),
|
||||||
@ -209,7 +209,7 @@ suspend fun Command.execute(sender: CommandSender, args: MessageChain, checkPerm
|
|||||||
*/
|
*/
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
@Throws(CommandExecutionException::class)
|
@Throws(CommandExecutionException::class)
|
||||||
suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean = true) {
|
public suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermission: Boolean = true) {
|
||||||
sender.executeCommandInternal(
|
sender.executeCommandInternal(
|
||||||
this,
|
this,
|
||||||
args.flattenCommandComponents().toTypedArray(),
|
args.flattenCommandComponents().toTypedArray(),
|
||||||
@ -229,7 +229,7 @@ suspend fun Command.execute(sender: CommandSender, vararg args: Any, checkPermis
|
|||||||
*
|
*
|
||||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||||
*/
|
*/
|
||||||
suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
||||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||||
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
||||||
}
|
}
|
||||||
@ -243,7 +243,7 @@ suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandE
|
|||||||
*
|
*
|
||||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||||
*/
|
*/
|
||||||
suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
||||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||||
return executeCommandDetailedInternal(messages, messages[0].toString())
|
return executeCommandDetailedInternal(messages, messages[0].toString())
|
||||||
}
|
}
|
||||||
|
@ -22,48 +22,48 @@ import net.mamoe.mirai.contact.isOwner
|
|||||||
*
|
*
|
||||||
* @see AnonymousCommandPermission
|
* @see AnonymousCommandPermission
|
||||||
*/
|
*/
|
||||||
interface CommandPermission {
|
public interface CommandPermission {
|
||||||
/**
|
/**
|
||||||
* 判断 [this] 是否拥有这个指令的权限
|
* 判断 [this] 是否拥有这个指令的权限
|
||||||
*
|
*
|
||||||
* @see CommandSender.hasPermission
|
* @see CommandSender.hasPermission
|
||||||
* @see CommandPermission.testPermission
|
* @see CommandPermission.testPermission
|
||||||
*/
|
*/
|
||||||
fun CommandSender.hasPermission(): Boolean
|
public fun CommandSender.hasPermission(): Boolean
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 满足两个权限其中一个即可使用指令
|
* 满足两个权限其中一个即可使用指令
|
||||||
*/ // no extension for Java
|
*/ // no extension for Java
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
infix fun or(another: CommandPermission): CommandPermission = OrCommandPermission(this, another)
|
public infix fun or(another: CommandPermission): CommandPermission = OrCommandPermission(this, another)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 同时拥有两个权限才能使用指令
|
* 同时拥有两个权限才能使用指令
|
||||||
*/ // no extension for Java
|
*/ // no extension for Java
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
infix fun and(another: CommandPermission): CommandPermission = AndCommandPermission(this, another)
|
public infix fun and(another: CommandPermission): CommandPermission = AndCommandPermission(this, another)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任何人都可以使用这个指令
|
* 任何人都可以使用这个指令
|
||||||
*/
|
*/
|
||||||
object Any : CommandPermission {
|
public object Any : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean = true
|
public override fun CommandSender.hasPermission(): Boolean = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 任何人都不能使用这个指令. 指令只能通过调用 [Command.onCommand] 执行.
|
* 任何人都不能使用这个指令. 指令只能通过调用 [Command.onCommand] 执行.
|
||||||
*/
|
*/
|
||||||
object None : CommandPermission {
|
public object None : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean = false
|
public override fun CommandSender.hasPermission(): Boolean = false
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 来自任何 [Bot] 的任何一个管理员或群主都可以使用这个指令
|
* 来自任何 [Bot] 的任何一个管理员或群主都可以使用这个指令
|
||||||
*/
|
*/
|
||||||
object Operator : CommandPermission {
|
public object Operator : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean {
|
public override fun CommandSender.hasPermission(): Boolean {
|
||||||
return this is MemberCommandSender && this.user.isOperator()
|
return this is MemberCommandSender && this.user.isOperator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -71,8 +71,8 @@ interface CommandPermission {
|
|||||||
/**
|
/**
|
||||||
* 来自任何 [Bot] 的任何一个群主都可以使用这个指令
|
* 来自任何 [Bot] 的任何一个群主都可以使用这个指令
|
||||||
*/
|
*/
|
||||||
object GroupOwner : CommandPermission {
|
public object GroupOwner : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean {
|
public override fun CommandSender.hasPermission(): Boolean {
|
||||||
return this is MemberCommandSender && this.user.isOwner()
|
return this is MemberCommandSender && this.user.isOwner()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -80,8 +80,8 @@ interface CommandPermission {
|
|||||||
/**
|
/**
|
||||||
* 管理员 (不包含群主) 可以使用这个指令
|
* 管理员 (不包含群主) 可以使用这个指令
|
||||||
*/
|
*/
|
||||||
object Administrator : CommandPermission {
|
public object Administrator : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean {
|
public override fun CommandSender.hasPermission(): Boolean {
|
||||||
return this is MemberCommandSender && this.user.isAdministrator()
|
return this is MemberCommandSender && this.user.isAdministrator()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,8 +89,8 @@ interface CommandPermission {
|
|||||||
/**
|
/**
|
||||||
* 任何 [Bot] 的 manager 都可以使用这个指令
|
* 任何 [Bot] 的 manager 都可以使用这个指令
|
||||||
*/
|
*/
|
||||||
object Manager : CommandPermission {
|
public object Manager : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean {
|
public override fun CommandSender.hasPermission(): Boolean {
|
||||||
return this is MemberCommandSender && this.user.isManager
|
return this is MemberCommandSender && this.user.isManager
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,11 +98,11 @@ interface CommandPermission {
|
|||||||
/**
|
/**
|
||||||
* 仅控制台能使用和这个指令
|
* 仅控制台能使用和这个指令
|
||||||
*/
|
*/
|
||||||
object Console : CommandPermission {
|
public object Console : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean = this is ConsoleCommandSender
|
public override fun CommandSender.hasPermission(): Boolean = this is ConsoleCommandSender
|
||||||
}
|
}
|
||||||
|
|
||||||
object Default : CommandPermission by (Manager or Console)
|
public object Default : CommandPermission by (Manager or Console)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -110,19 +110,19 @@ interface CommandPermission {
|
|||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
inline fun AnonymousCommandPermission(crossinline block: CommandSender.() -> Boolean): CommandPermission {
|
public inline fun AnonymousCommandPermission(crossinline block: CommandSender.() -> Boolean): CommandPermission {
|
||||||
return object : CommandPermission {
|
return object : CommandPermission {
|
||||||
override fun CommandSender.hasPermission(): Boolean = block()
|
override fun CommandSender.hasPermission(): Boolean = block()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fun CommandSender.hasPermission(permission: CommandPermission): Boolean =
|
public inline fun CommandSender.hasPermission(permission: CommandPermission): Boolean =
|
||||||
permission.run { this@hasPermission.hasPermission() }
|
permission.run { this@hasPermission.hasPermission() }
|
||||||
|
|
||||||
|
|
||||||
inline fun CommandPermission.testPermission(sender: CommandSender): Boolean = this.run { sender.hasPermission() }
|
public inline fun CommandPermission.testPermission(sender: CommandSender): Boolean = this.run { sender.hasPermission() }
|
||||||
|
|
||||||
inline fun Command.testPermission(sender: CommandSender): Boolean = sender.hasPermission(this.permission)
|
public inline fun Command.testPermission(sender: CommandSender): Boolean = sender.hasPermission(this.permission)
|
||||||
|
|
||||||
internal class OrCommandPermission(
|
internal class OrCommandPermission(
|
||||||
private val first: CommandPermission,
|
private val first: CommandPermission,
|
||||||
|
@ -14,12 +14,12 @@ package net.mamoe.mirai.console.command
|
|||||||
*
|
*
|
||||||
* 总是作为 [CommandExecutionException.cause].
|
* 总是作为 [CommandExecutionException.cause].
|
||||||
*/
|
*/
|
||||||
class CommandPermissionDeniedException(
|
public class CommandPermissionDeniedException(
|
||||||
/**
|
/**
|
||||||
* 执行过程发生异常的指令
|
* 执行过程发生异常的指令
|
||||||
*/
|
*/
|
||||||
val command: Command
|
public val command: Command
|
||||||
) : RuntimeException("Permission denied while executing command '${command.primaryName}'") {
|
) : RuntimeException("Permission denied while executing command '${command.primaryName}'") {
|
||||||
override fun toString(): String =
|
public override fun toString(): String =
|
||||||
"CommandPermissionDeniedException(command=$command)"
|
"CommandPermissionDeniedException(command=$command)"
|
||||||
}
|
}
|
@ -28,55 +28,55 @@ import net.mamoe.mirai.message.data.PlainText
|
|||||||
* @see UserCommandSender
|
* @see UserCommandSender
|
||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
interface CommandSender {
|
public interface CommandSender {
|
||||||
/**
|
/**
|
||||||
* 与这个 [CommandSender] 相关的 [Bot]. 当通过控制台执行时为 null.
|
* 与这个 [CommandSender] 相关的 [Bot]. 当通过控制台执行时为 null.
|
||||||
*/
|
*/
|
||||||
val bot: Bot?
|
public val bot: Bot?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 立刻发送一条消息
|
* 立刻发送一条消息
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
suspend fun sendMessage(message: Message)
|
public suspend fun sendMessage(message: Message)
|
||||||
|
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
@JavaFriendlyAPI
|
@JavaFriendlyAPI
|
||||||
@JvmName("sendMessage")
|
@JvmName("sendMessage")
|
||||||
fun __sendMessageBlocking(messageChain: Message) = runBlocking { sendMessage(messageChain) }
|
public fun __sendMessageBlocking(messageChain: Message): Unit = runBlocking { sendMessage(messageChain) }
|
||||||
|
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
@JavaFriendlyAPI
|
@JavaFriendlyAPI
|
||||||
@JvmName("sendMessage")
|
@JvmName("sendMessage")
|
||||||
fun __sendMessageBlocking(message: String) = runBlocking { sendMessage(message) }
|
public fun __sendMessageBlocking(message: String): Unit = runBlocking { sendMessage(message) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可以知道其 [Bot] 的 [CommandSender]
|
* 可以知道其 [Bot] 的 [CommandSender]
|
||||||
*/
|
*/
|
||||||
interface BotAwareCommandSender : CommandSender {
|
public interface BotAwareCommandSender : CommandSender {
|
||||||
override val bot: Bot
|
public override val bot: Bot
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend inline fun CommandSender.sendMessage(message: String) = sendMessage(PlainText(message))
|
public suspend inline fun CommandSender.sendMessage(message: String): Unit = sendMessage(PlainText(message))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 控制台指令执行者. 代表由控制台执行指令
|
* 控制台指令执行者. 代表由控制台执行指令
|
||||||
*/
|
*/
|
||||||
// 前端实现
|
// 前端实现
|
||||||
abstract class ConsoleCommandSender internal constructor() : CommandSender {
|
public abstract class ConsoleCommandSender internal constructor() : CommandSender {
|
||||||
final override val bot: Nothing? get() = null
|
public final override val bot: Nothing? get() = null
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
internal val instance get() = MiraiConsoleInternal.consoleCommandSender
|
internal val instance get() = MiraiConsoleInternal.consoleCommandSender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Friend.asCommandSender(): FriendCommandSender = FriendCommandSender(this)
|
public fun Friend.asCommandSender(): FriendCommandSender = FriendCommandSender(this)
|
||||||
|
|
||||||
fun Member.asCommandSender(): MemberCommandSender = MemberCommandSender(this)
|
public fun Member.asCommandSender(): MemberCommandSender = MemberCommandSender(this)
|
||||||
|
|
||||||
fun User.asCommandSender(): UserCommandSender {
|
public fun User.asCommandSender(): UserCommandSender {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is Friend -> this.asCommandSender()
|
is Friend -> this.asCommandSender()
|
||||||
is Member -> this.asCommandSender()
|
is Member -> this.asCommandSender()
|
||||||
@ -87,28 +87,28 @@ fun User.asCommandSender(): UserCommandSender {
|
|||||||
/**
|
/**
|
||||||
* 表示由 [MessageEvent] 触发的指令
|
* 表示由 [MessageEvent] 触发的指令
|
||||||
*/
|
*/
|
||||||
interface MessageEventContextAware<E : MessageEvent> : MessageEventExtensions<User, Contact> {
|
public interface MessageEventContextAware<E : MessageEvent> : MessageEventExtensions<User, Contact> {
|
||||||
val fromEvent: E
|
public val fromEvent: E
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代表一个用户私聊机器人执行指令
|
* 代表一个用户私聊机器人执行指令
|
||||||
* @see User.asCommandSender
|
* @see User.asCommandSender
|
||||||
*/
|
*/
|
||||||
sealed class UserCommandSender : CommandSender, BotAwareCommandSender {
|
public sealed class UserCommandSender : CommandSender, BotAwareCommandSender {
|
||||||
/**
|
/**
|
||||||
* @see MessageEvent.sender
|
* @see MessageEvent.sender
|
||||||
*/
|
*/
|
||||||
abstract val user: User
|
public abstract val user: User
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see MessageEvent.subject
|
* @see MessageEvent.subject
|
||||||
*/
|
*/
|
||||||
abstract val subject: Contact
|
public abstract val subject: Contact
|
||||||
|
|
||||||
override val bot: Bot get() = user.bot
|
public override val bot: Bot get() = user.bot
|
||||||
|
|
||||||
final override suspend fun sendMessage(message: Message) {
|
public final override suspend fun sendMessage(message: Message) {
|
||||||
subject.sendMessage(message)
|
subject.sendMessage(message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,37 +117,39 @@ sealed class UserCommandSender : CommandSender, BotAwareCommandSender {
|
|||||||
* 代表一个用户私聊机器人执行指令
|
* 代表一个用户私聊机器人执行指令
|
||||||
* @see Friend.asCommandSender
|
* @see Friend.asCommandSender
|
||||||
*/
|
*/
|
||||||
open class FriendCommandSender(final override val user: Friend) : UserCommandSender() {
|
public open class FriendCommandSender(final override val user: Friend) : UserCommandSender() {
|
||||||
override val subject: Contact get() = user
|
public override val subject: Contact get() = user
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代表一个用户私聊机器人执行指令
|
* 代表一个用户私聊机器人执行指令
|
||||||
* @see Friend.asCommandSender
|
* @see Friend.asCommandSender
|
||||||
*/
|
*/
|
||||||
class FriendCommandSenderOnMessage(override val fromEvent: FriendMessageEvent) : FriendCommandSender(fromEvent.sender),
|
public class FriendCommandSenderOnMessage(override val fromEvent: FriendMessageEvent) :
|
||||||
|
FriendCommandSender(fromEvent.sender),
|
||||||
MessageEventContextAware<FriendMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
MessageEventContextAware<FriendMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
||||||
override val subject: Contact get() = super.subject
|
public override val subject: Contact get() = super.subject
|
||||||
override val bot: Bot get() = super.bot
|
public override val bot: Bot get() = super.bot
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代表一个群成员执行指令.
|
* 代表一个群成员执行指令.
|
||||||
* @see Member.asCommandSender
|
* @see Member.asCommandSender
|
||||||
*/
|
*/
|
||||||
open class MemberCommandSender(final override val user: Member) : UserCommandSender() {
|
public open class MemberCommandSender(final override val user: Member) : UserCommandSender() {
|
||||||
inline val group: Group get() = user.group
|
public inline val group: Group get() = user.group
|
||||||
override val subject: Contact get() = group
|
public override val subject: Contact get() = group
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 代表一个群成员在群内执行指令.
|
* 代表一个群成员在群内执行指令.
|
||||||
* @see Member.asCommandSender
|
* @see Member.asCommandSender
|
||||||
*/
|
*/
|
||||||
class MemberCommandSenderOnMessage(override val fromEvent: GroupMessageEvent) : MemberCommandSender(fromEvent.sender),
|
public class MemberCommandSenderOnMessage(override val fromEvent: GroupMessageEvent) :
|
||||||
|
MemberCommandSender(fromEvent.sender),
|
||||||
MessageEventContextAware<GroupMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
MessageEventContextAware<GroupMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
||||||
override val subject: Contact get() = super.subject
|
public override val subject: Contact get() = super.subject
|
||||||
override val bot: Bot get() = super.bot
|
public override val bot: Bot get() = super.bot
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -155,8 +157,9 @@ class MemberCommandSenderOnMessage(override val fromEvent: GroupMessageEvent) :
|
|||||||
* @see Member.asCommandSender
|
* @see Member.asCommandSender
|
||||||
*/
|
*/
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
class TempCommandSenderOnMessage(override val fromEvent: TempMessageEvent) : MemberCommandSender(fromEvent.sender),
|
public class TempCommandSenderOnMessage(override val fromEvent: TempMessageEvent) :
|
||||||
|
MemberCommandSender(fromEvent.sender),
|
||||||
MessageEventContextAware<TempMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
MessageEventContextAware<TempMessageEvent>, MessageEventExtensions<User, Contact> by fromEvent {
|
||||||
override val subject: Contact get() = super.subject
|
public override val subject: Contact get() = super.subject
|
||||||
override val bot: Bot get() = super.bot
|
public override val bot: Bot get() = super.bot
|
||||||
}
|
}
|
@ -11,8 +11,8 @@
|
|||||||
"EXPOSED_SUPER_CLASS",
|
"EXPOSED_SUPER_CLASS",
|
||||||
"NOTHING_TO_INLINE",
|
"NOTHING_TO_INLINE",
|
||||||
"unused",
|
"unused",
|
||||||
"WRONG_MODIFIER_TARGET",
|
"WRONG_MODIFIER_TARGET", "CANNOT_WEAKEN_ACCESS_PRIVILEGE",
|
||||||
"WRONG_MODIFIER_CONTAINING_DECLARATION"
|
"WRONG_MODIFIER_CONTAINING_DECLARATION", "RedundantVisibilityModifier"
|
||||||
)
|
)
|
||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
@ -29,7 +29,7 @@ import kotlin.reflect.KClass
|
|||||||
* 复合指令.
|
* 复合指令.
|
||||||
*/
|
*/
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
abstract class CompositeCommand @JvmOverloads constructor(
|
public abstract class CompositeCommand @JvmOverloads constructor(
|
||||||
owner: CommandOwner,
|
owner: CommandOwner,
|
||||||
vararg names: String,
|
vararg names: String,
|
||||||
description: String = "no description available",
|
description: String = "no description available",
|
||||||
@ -41,7 +41,7 @@ abstract class CompositeCommand @JvmOverloads constructor(
|
|||||||
/**
|
/**
|
||||||
* [CommandArgParser] 的环境
|
* [CommandArgParser] 的环境
|
||||||
*/
|
*/
|
||||||
final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
public final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 标记一个函数为子指令, 当 [value] 为空时使用函数名.
|
* 标记一个函数为子指令, 当 [value] 为空时使用函数名.
|
||||||
@ -66,16 +66,17 @@ abstract class CompositeCommand @JvmOverloads constructor(
|
|||||||
@Target(AnnotationTarget.VALUE_PARAMETER)
|
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||||
protected annotation class Name(val value: String)
|
protected annotation class Name(val value: String)
|
||||||
|
|
||||||
override suspend fun CommandSender.onDefault(rawArgs: Array<out Any>) {
|
public final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
||||||
sendMessage(usage)
|
|
||||||
}
|
|
||||||
|
|
||||||
final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
|
||||||
matchSubCommand(args)?.parseAndExecute(this, args, true) ?: kotlin.run {
|
matchSubCommand(args)?.parseAndExecute(this, args, true) ?: kotlin.run {
|
||||||
defaultSubCommand.onCommand(this, args)
|
defaultSubCommand.onCommand(this, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final override val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
|
||||||
|
internal override suspend fun CommandSender.onDefault(rawArgs: Array<out Any>) {
|
||||||
|
sendMessage(usage)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal final override val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
||||||
get() = CompositeCommandSubCommandAnnotationResolver
|
get() = CompositeCommandSubCommandAnnotationResolver
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
|
|
||||||
abstract class RawCommand(
|
public abstract class RawCommand(
|
||||||
override val owner: CommandOwner,
|
public override val owner: CommandOwner,
|
||||||
override vararg val names: String,
|
public override vararg val names: String,
|
||||||
override val usage: String = "<no usages given>",
|
public override val usage: String = "<no usages given>",
|
||||||
override val description: String = "<no descriptions given>",
|
public override val description: String = "<no descriptions given>",
|
||||||
override val permission: CommandPermission = CommandPermission.Default,
|
public override val permission: CommandPermission = CommandPermission.Default,
|
||||||
override val prefixOptional: Boolean = false
|
public override val prefixOptional: Boolean = false
|
||||||
) : Command {
|
) : Command {
|
||||||
abstract override suspend fun CommandSender.onCommand(args: Array<out Any>)
|
public abstract override suspend fun CommandSender.onCommand(args: Array<out Any>)
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,8 @@
|
|||||||
"EXPOSED_SUPER_CLASS",
|
"EXPOSED_SUPER_CLASS",
|
||||||
"NOTHING_TO_INLINE",
|
"NOTHING_TO_INLINE",
|
||||||
"unused",
|
"unused",
|
||||||
"WRONG_MODIFIER_TARGET",
|
"WRONG_MODIFIER_TARGET", "CANNOT_WEAKEN_ACCESS_PRIVILEGE",
|
||||||
"WRONG_MODIFIER_CONTAINING_DECLARATION"
|
"WRONG_MODIFIER_CONTAINING_DECLARATION", "RedundantVisibilityModifier"
|
||||||
)
|
)
|
||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
package net.mamoe.mirai.console.command
|
||||||
@ -24,7 +24,7 @@ import net.mamoe.mirai.console.command.description.plus
|
|||||||
import net.mamoe.mirai.console.command.internal.AbstractReflectionCommand
|
import net.mamoe.mirai.console.command.internal.AbstractReflectionCommand
|
||||||
import net.mamoe.mirai.console.command.internal.SimpleCommandSubCommandAnnotationResolver
|
import net.mamoe.mirai.console.command.internal.SimpleCommandSubCommandAnnotationResolver
|
||||||
|
|
||||||
abstract class SimpleCommand @JvmOverloads constructor(
|
public abstract class SimpleCommand @JvmOverloads constructor(
|
||||||
owner: CommandOwner,
|
owner: CommandOwner,
|
||||||
vararg names: String,
|
vararg names: String,
|
||||||
description: String = "no description available",
|
description: String = "no description available",
|
||||||
@ -34,7 +34,7 @@ abstract class SimpleCommand @JvmOverloads constructor(
|
|||||||
) : Command, AbstractReflectionCommand(owner, names, description, permission, prefixOptional),
|
) : Command, AbstractReflectionCommand(owner, names, description, permission, prefixOptional),
|
||||||
CommandParserContextAware {
|
CommandParserContextAware {
|
||||||
|
|
||||||
override val usage: String
|
public override val usage: String
|
||||||
get() = super.usage
|
get() = super.usage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -42,20 +42,20 @@ abstract class SimpleCommand @JvmOverloads constructor(
|
|||||||
*/
|
*/
|
||||||
protected annotation class Handler
|
protected annotation class Handler
|
||||||
|
|
||||||
final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
public final override val context: CommandParserContext = CommandParserContext.Builtins + overrideContext
|
||||||
|
|
||||||
override fun checkSubCommand(subCommands: Array<SubCommandDescriptor>) {
|
internal override fun checkSubCommand(subCommands: Array<SubCommandDescriptor>) {
|
||||||
super.checkSubCommand(subCommands)
|
super.checkSubCommand(subCommands)
|
||||||
check(subCommands.size == 1) { "There can only be exactly one function annotated with Handler at this moment as overloading is not yet supported." }
|
check(subCommands.size == 1) { "There can only be exactly one function annotated with Handler at this moment as overloading is not yet supported." }
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated("prohibited", level = DeprecationLevel.HIDDEN)
|
@Deprecated("prohibited", level = DeprecationLevel.HIDDEN)
|
||||||
override suspend fun CommandSender.onDefault(rawArgs: Array<out Any>) = sendMessage(usage)
|
internal override suspend fun CommandSender.onDefault(rawArgs: Array<out Any>) = sendMessage(usage)
|
||||||
|
|
||||||
final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
public final override suspend fun CommandSender.onCommand(args: Array<out Any>) {
|
||||||
subCommands.single().parseAndExecute(this, args, false)
|
subCommands.single().parseAndExecute(this, args, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
final override val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
internal final override val subCommandAnnotationResolver: SubCommandAnnotationResolver
|
||||||
get() = SimpleCommandSubCommandAnnotationResolver
|
get() = SimpleCommandSubCommandAnnotationResolver
|
||||||
}
|
}
|
@ -20,14 +20,14 @@ import kotlin.contracts.contract
|
|||||||
* this output type of that arg
|
* this output type of that arg
|
||||||
* input is always String
|
* input is always String
|
||||||
*/
|
*/
|
||||||
interface CommandArgParser<out T : Any> {
|
public interface CommandArgParser<out T : Any> {
|
||||||
fun parse(raw: String, sender: CommandSender): T
|
public fun parse(raw: String, sender: CommandSender): T
|
||||||
|
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
fun parse(raw: SingleMessage, sender: CommandSender): T = parse(raw.content, sender)
|
public fun parse(raw: SingleMessage, sender: CommandSender): T = parse(raw.content, sender)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Any> CommandArgParser<T>.parse(raw: Any, sender: CommandSender): T {
|
public fun <T : Any> CommandArgParser<T>.parse(raw: Any, sender: CommandSender): T {
|
||||||
contract {
|
contract {
|
||||||
returns() implies (raw is String || raw is SingleMessage)
|
returns() implies (raw is String || raw is SingleMessage)
|
||||||
}
|
}
|
||||||
@ -41,12 +41,12 @@ fun <T : Any> CommandArgParser<T>.parse(raw: Any, sender: CommandSender): T {
|
|||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline fun CommandArgParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
public inline fun CommandArgParser<*>.illegalArgument(message: String, cause: Throwable? = null): Nothing {
|
||||||
throw ParserException(message, cause)
|
throw ParserException(message, cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline fun CommandArgParser<*>.checkArgument(
|
public inline fun CommandArgParser<*>.checkArgument(
|
||||||
condition: Boolean,
|
condition: Boolean,
|
||||||
crossinline message: () -> String = { "Check failed." }
|
crossinline message: () -> String = { "Check failed." }
|
||||||
) {
|
) {
|
||||||
@ -61,7 +61,7 @@ inline fun CommandArgParser<*>.checkArgument(
|
|||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline fun <T : Any> CommandArgParser(
|
public inline fun <T : Any> CommandArgParser(
|
||||||
crossinline stringParser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T
|
crossinline stringParser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T
|
||||||
): CommandArgParser<T> = object : CommandArgParser<T> {
|
): CommandArgParser<T> = object : CommandArgParser<T> {
|
||||||
override fun parse(raw: String, sender: CommandSender): T = stringParser(raw, sender)
|
override fun parse(raw: String, sender: CommandSender): T = stringParser(raw, sender)
|
||||||
@ -72,7 +72,7 @@ inline fun <T : Any> CommandArgParser(
|
|||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline fun <T : Any> CommandArgParser(
|
public inline fun <T : Any> CommandArgParser(
|
||||||
crossinline stringParser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T,
|
crossinline stringParser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T,
|
||||||
crossinline messageParser: CommandArgParser<T>.(m: SingleMessage, sender: CommandSender) -> T
|
crossinline messageParser: CommandArgParser<T>.(m: SingleMessage, sender: CommandSender) -> T
|
||||||
): CommandArgParser<T> = object : CommandArgParser<T> {
|
): CommandArgParser<T> = object : CommandArgParser<T> {
|
||||||
@ -84,4 +84,4 @@ inline fun <T : Any> CommandArgParser(
|
|||||||
/**
|
/**
|
||||||
* 在解析参数时遇到的 _正常_ 错误. 如参数不符合规范.
|
* 在解析参数时遇到的 _正常_ 错误. 如参数不符合规范.
|
||||||
*/
|
*/
|
||||||
class ParserException(message: String, cause: Throwable? = null) : RuntimeException(message, cause)
|
public class ParserException(message: String, cause: Throwable? = null) : RuntimeException(message, cause)
|
@ -23,44 +23,44 @@ import net.mamoe.mirai.message.data.SingleMessage
|
|||||||
import net.mamoe.mirai.message.data.content
|
import net.mamoe.mirai.message.data.content
|
||||||
|
|
||||||
|
|
||||||
object IntArgParser : CommandArgParser<Int> {
|
public object IntArgParser : CommandArgParser<Int> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Int =
|
public override fun parse(raw: String, sender: CommandSender): Int =
|
||||||
raw.toIntOrNull() ?: illegalArgument("无法解析 $raw 为整数")
|
raw.toIntOrNull() ?: illegalArgument("无法解析 $raw 为整数")
|
||||||
}
|
}
|
||||||
|
|
||||||
object LongArgParser : CommandArgParser<Long> {
|
public object LongArgParser : CommandArgParser<Long> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Long =
|
public override fun parse(raw: String, sender: CommandSender): Long =
|
||||||
raw.toLongOrNull() ?: illegalArgument("无法解析 $raw 为长整数")
|
raw.toLongOrNull() ?: illegalArgument("无法解析 $raw 为长整数")
|
||||||
}
|
}
|
||||||
|
|
||||||
object ShortArgParser : CommandArgParser<Short> {
|
public object ShortArgParser : CommandArgParser<Short> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Short =
|
public override fun parse(raw: String, sender: CommandSender): Short =
|
||||||
raw.toShortOrNull() ?: illegalArgument("无法解析 $raw 为短整数")
|
raw.toShortOrNull() ?: illegalArgument("无法解析 $raw 为短整数")
|
||||||
}
|
}
|
||||||
|
|
||||||
object ByteArgParser : CommandArgParser<Byte> {
|
public object ByteArgParser : CommandArgParser<Byte> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Byte =
|
public override fun parse(raw: String, sender: CommandSender): Byte =
|
||||||
raw.toByteOrNull() ?: illegalArgument("无法解析 $raw 为字节")
|
raw.toByteOrNull() ?: illegalArgument("无法解析 $raw 为字节")
|
||||||
}
|
}
|
||||||
|
|
||||||
object DoubleArgParser : CommandArgParser<Double> {
|
public object DoubleArgParser : CommandArgParser<Double> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Double =
|
public override fun parse(raw: String, sender: CommandSender): Double =
|
||||||
raw.toDoubleOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
raw.toDoubleOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||||
}
|
}
|
||||||
|
|
||||||
object FloatArgParser : CommandArgParser<Float> {
|
public object FloatArgParser : CommandArgParser<Float> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Float =
|
public override fun parse(raw: String, sender: CommandSender): Float =
|
||||||
raw.toFloatOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
raw.toFloatOrNull() ?: illegalArgument("无法解析 $raw 为小数")
|
||||||
}
|
}
|
||||||
|
|
||||||
object StringArgParser : CommandArgParser<String> {
|
public object StringArgParser : CommandArgParser<String> {
|
||||||
override fun parse(raw: String, sender: CommandSender): String {
|
public override fun parse(raw: String, sender: CommandSender): String {
|
||||||
return raw
|
return raw
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object BooleanArgParser : CommandArgParser<Boolean> {
|
public object BooleanArgParser : CommandArgParser<Boolean> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str ->
|
public override fun parse(raw: String, sender: CommandSender): Boolean = raw.trim().let { str ->
|
||||||
str.equals("true", ignoreCase = true)
|
str.equals("true", ignoreCase = true)
|
||||||
|| str.equals("yes", ignoreCase = true)
|
|| str.equals("yes", ignoreCase = true)
|
||||||
|| str.equals("enabled", ignoreCase = true)
|
|| str.equals("enabled", ignoreCase = true)
|
||||||
@ -73,18 +73,18 @@ object BooleanArgParser : CommandArgParser<Boolean> {
|
|||||||
* output: Bot
|
* output: Bot
|
||||||
* errors: String->Int convert, Bot Not Exist
|
* errors: String->Int convert, Bot Not Exist
|
||||||
*/
|
*/
|
||||||
object ExistBotArgParser : CommandArgParser<Bot> {
|
public object ExistBotArgParser : CommandArgParser<Bot> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Bot {
|
public override fun parse(raw: String, sender: CommandSender): Bot {
|
||||||
val uin = raw.toLongOrNull() ?: illegalArgument("无法识别 QQ ID: $raw")
|
val uin = raw.toLongOrNull() ?: illegalArgument("无法识别 QQ ID: $raw")
|
||||||
return Bot.getInstanceOrNull(uin) ?: illegalArgument("无法找到 Bot $uin")
|
return Bot.getInstanceOrNull(uin) ?: illegalArgument("无法找到 Bot $uin")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ExistFriendArgParser : CommandArgParser<Friend> {
|
public object ExistFriendArgParser : CommandArgParser<Friend> {
|
||||||
//Bot.friend
|
//Bot.friend
|
||||||
//friend
|
//friend
|
||||||
//~ = self
|
//~ = self
|
||||||
override fun parse(raw: String, sender: CommandSender): Friend {
|
public override fun parse(raw: String, sender: CommandSender): Friend {
|
||||||
if (raw == "~") {
|
if (raw == "~") {
|
||||||
if (sender !is BotAwareCommandSender) {
|
if (sender !is BotAwareCommandSender) {
|
||||||
illegalArgument("无法解析~作为默认")
|
illegalArgument("无法解析~作为默认")
|
||||||
@ -115,7 +115,7 @@ object ExistFriendArgParser : CommandArgParser<Friend> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun parse(raw: SingleMessage, sender: CommandSender): Friend {
|
public override fun parse(raw: SingleMessage, sender: CommandSender): Friend {
|
||||||
if (raw is At) {
|
if (raw is At) {
|
||||||
assert(sender is MemberCommandSender)
|
assert(sender is MemberCommandSender)
|
||||||
return (sender as BotAwareCommandSender).bot.friends.getOrNull(raw.target) ?: illegalArgument("At的对象非Bot好友")
|
return (sender as BotAwareCommandSender).bot.friends.getOrNull(raw.target) ?: illegalArgument("At的对象非Bot好友")
|
||||||
@ -125,8 +125,8 @@ object ExistFriendArgParser : CommandArgParser<Friend> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ExistGroupArgParser : CommandArgParser<Group> {
|
public object ExistGroupArgParser : CommandArgParser<Group> {
|
||||||
override fun parse(raw: String, sender: CommandSender): Group {
|
public override fun parse(raw: String, sender: CommandSender): Group {
|
||||||
//by default
|
//by default
|
||||||
if ((raw == "" || raw == "~") && sender is MemberCommandSender) {
|
if ((raw == "" || raw == "~") && sender is MemberCommandSender) {
|
||||||
return sender.group
|
return sender.group
|
||||||
@ -160,12 +160,12 @@ object ExistGroupArgParser : CommandArgParser<Group> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object ExistMemberArgParser : CommandArgParser<Member> {
|
public object ExistMemberArgParser : CommandArgParser<Member> {
|
||||||
//后台: Bot.Group.Member[QQ/名片]
|
//后台: Bot.Group.Member[QQ/名片]
|
||||||
//私聊: Group.Member[QQ/名片]
|
//私聊: Group.Member[QQ/名片]
|
||||||
//群内: Q号
|
//群内: Q号
|
||||||
//群内: 名片
|
//群内: 名片
|
||||||
override fun parse(raw: String, sender: CommandSender): Member {
|
public override fun parse(raw: String, sender: CommandSender): Member {
|
||||||
if (sender !is BotAwareCommandSender) {
|
if (sender !is BotAwareCommandSender) {
|
||||||
with(raw.split(".")) {
|
with(raw.split(".")) {
|
||||||
checkArgument(this.size >= 3) {
|
checkArgument(this.size >= 3) {
|
||||||
@ -226,7 +226,7 @@ object ExistMemberArgParser : CommandArgParser<Member> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun parse(raw: SingleMessage, sender: CommandSender): Member {
|
public override fun parse(raw: SingleMessage, sender: CommandSender): Member {
|
||||||
return if (raw is At) {
|
return if (raw is At) {
|
||||||
checkArgument(sender is MemberCommandSender)
|
checkArgument(sender is MemberCommandSender)
|
||||||
(sender.group).members[raw.target]
|
(sender.group).members[raw.target]
|
||||||
|
@ -27,20 +27,20 @@ import kotlin.reflect.full.isSubclassOf
|
|||||||
* [KClass] 到 [CommandArgParser] 的匹配
|
* [KClass] 到 [CommandArgParser] 的匹配
|
||||||
* @see CustomCommandParserContext 自定义
|
* @see CustomCommandParserContext 自定义
|
||||||
*/
|
*/
|
||||||
interface CommandParserContext {
|
public interface CommandParserContext {
|
||||||
data class ParserPair<T : Any>(
|
public data class ParserPair<T : Any>(
|
||||||
val klass: KClass<T>,
|
val klass: KClass<T>,
|
||||||
val parser: CommandArgParser<T>
|
val parser: CommandArgParser<T>
|
||||||
)
|
)
|
||||||
|
|
||||||
operator fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>?
|
public operator fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>?
|
||||||
|
|
||||||
fun toList(): List<ParserPair<*>>
|
public fun toList(): List<ParserPair<*>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内建的默认 [CommandArgParser]
|
* 内建的默认 [CommandArgParser]
|
||||||
*/
|
*/
|
||||||
object Builtins : CommandParserContext by (CommandParserContext {
|
public object Builtins : CommandParserContext by (CommandParserContext {
|
||||||
Int::class with IntArgParser
|
Int::class with IntArgParser
|
||||||
Byte::class with ByteArgParser
|
Byte::class with ByteArgParser
|
||||||
Short::class with ShortArgParser
|
Short::class with ShortArgParser
|
||||||
@ -60,19 +60,19 @@ interface CommandParserContext {
|
|||||||
/**
|
/**
|
||||||
* 拥有 [CommandParserContext] 的类
|
* 拥有 [CommandParserContext] 的类
|
||||||
*/
|
*/
|
||||||
interface CommandParserContextAware {
|
public interface CommandParserContextAware {
|
||||||
/**
|
/**
|
||||||
* [CommandArgParser] 的环境
|
* [CommandArgParser] 的环境
|
||||||
*/
|
*/
|
||||||
val context: CommandParserContext
|
public val context: CommandParserContext
|
||||||
}
|
}
|
||||||
|
|
||||||
object EmptyCommandParserContext : CommandParserContext by CustomCommandParserContext(listOf())
|
public object EmptyCommandParserContext : CommandParserContext by CustomCommandParserContext(listOf())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 合并两个 [CommandParserContext], [replacer] 将会替换 [this] 中重复的 parser.
|
* 合并两个 [CommandParserContext], [replacer] 将会替换 [this] 中重复的 parser.
|
||||||
*/
|
*/
|
||||||
operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandParserContext {
|
public operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandParserContext {
|
||||||
if (replacer == EmptyCommandParserContext) return this
|
if (replacer == EmptyCommandParserContext) return this
|
||||||
if (this == EmptyCommandParserContext) return replacer
|
if (this == EmptyCommandParserContext) return replacer
|
||||||
return object : CommandParserContext {
|
return object : CommandParserContext {
|
||||||
@ -84,7 +84,7 @@ operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandP
|
|||||||
/**
|
/**
|
||||||
* 合并 [this] 与 [replacer], [replacer] 将会替换 [this] 中重复的 parser.
|
* 合并 [this] 与 [replacer], [replacer] 将会替换 [this] 中重复的 parser.
|
||||||
*/
|
*/
|
||||||
operator fun CommandParserContext.plus(replacer: List<ParserPair<*>>): CommandParserContext {
|
public operator fun CommandParserContext.plus(replacer: List<ParserPair<*>>): CommandParserContext {
|
||||||
if (replacer.isEmpty()) return this
|
if (replacer.isEmpty()) return this
|
||||||
if (this == EmptyCommandParserContext) return CustomCommandParserContext(replacer)
|
if (this == EmptyCommandParserContext) return CustomCommandParserContext(replacer)
|
||||||
return object : CommandParserContext {
|
return object : CommandParserContext {
|
||||||
@ -97,7 +97,7 @@ operator fun CommandParserContext.plus(replacer: List<ParserPair<*>>): CommandPa
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
open class CustomCommandParserContext(val list: List<ParserPair<*>>) : CommandParserContext {
|
public open class CustomCommandParserContext(public val list: List<ParserPair<*>>) : CommandParserContext {
|
||||||
|
|
||||||
override fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>? =
|
override fun <T : Any> get(klass: KClass<out T>): CommandArgParser<T>? =
|
||||||
this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgParser<T>?
|
this.list.firstOrNull { klass.isSubclassOf(it.klass) }?.parser as CommandArgParser<T>?
|
||||||
@ -125,16 +125,16 @@ open class CustomCommandParserContext(val list: List<ParserPair<*>>) : CommandPa
|
|||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline fun CommandParserContext(block: CommandParserContextBuilder.() -> Unit): CommandParserContext {
|
public inline fun CommandParserContext(block: CommandParserContextBuilder.() -> Unit): CommandParserContext {
|
||||||
return CustomCommandParserContext(CommandParserContextBuilder().apply(block).distinctByReversed { it.klass })
|
return CustomCommandParserContext(CommandParserContextBuilder().apply(block).distinctByReversed { it.klass })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see CommandParserContext
|
* @see CommandParserContext
|
||||||
*/
|
*/
|
||||||
class CommandParserContextBuilder : MutableList<ParserPair<*>> by mutableListOf() {
|
public class CommandParserContextBuilder : MutableList<ParserPair<*>> by mutableListOf() {
|
||||||
@JvmName("add")
|
@JvmName("add")
|
||||||
inline infix fun <T : Any> KClass<T>.with(parser: CommandArgParser<T>): ParserPair<*> =
|
public inline infix fun <T : Any> KClass<T>.with(parser: CommandArgParser<T>): ParserPair<*> =
|
||||||
ParserPair(this, parser).also { add(it) }
|
ParserPair(this, parser).also { add(it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -142,7 +142,7 @@ class CommandParserContextBuilder : MutableList<ParserPair<*>> by mutableListOf(
|
|||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
@LowPriorityInOverloadResolution
|
@LowPriorityInOverloadResolution
|
||||||
inline infix fun <T : Any> KClass<T>.with(
|
public inline infix fun <T : Any> KClass<T>.with(
|
||||||
crossinline parser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T
|
crossinline parser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T
|
||||||
): ParserPair<*> = ParserPair(this, CommandArgParser(parser)).also { add(it) }
|
): ParserPair<*> = ParserPair(this, CommandArgParser(parser)).also { add(it) }
|
||||||
|
|
||||||
@ -150,12 +150,12 @@ class CommandParserContextBuilder : MutableList<ParserPair<*>> by mutableListOf(
|
|||||||
* 添加一个指令解析器
|
* 添加一个指令解析器
|
||||||
*/
|
*/
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline infix fun <T : Any> KClass<T>.with(
|
public inline infix fun <T : Any> KClass<T>.with(
|
||||||
crossinline parser: CommandArgParser<T>.(s: String) -> T
|
crossinline parser: CommandArgParser<T>.(s: String) -> T
|
||||||
): ParserPair<*> = ParserPair(this, CommandArgParser { s: String, _: CommandSender -> parser(s) }).also { add(it) }
|
): ParserPair<*> = ParserPair(this, CommandArgParser { s: String, _: CommandSender -> parser(s) }).also { add(it) }
|
||||||
|
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline fun <reified T : Any> add(parser: CommandArgParser<T>): ParserPair<*> =
|
public inline fun <reified T : Any> add(parser: CommandArgParser<T>): ParserPair<*> =
|
||||||
ParserPair(T::class, parser).also { add(it) }
|
ParserPair(T::class, parser).also { add(it) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -163,7 +163,7 @@ class CommandParserContextBuilder : MutableList<ParserPair<*>> by mutableListOf(
|
|||||||
*/
|
*/
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
inline infix fun <reified T : Any> add(
|
public inline infix fun <reified T : Any> add(
|
||||||
crossinline parser: CommandArgParser<*>.(s: String) -> T
|
crossinline parser: CommandArgParser<*>.(s: String) -> T
|
||||||
): ParserPair<*> = T::class with CommandArgParser { s: String, _: CommandSender -> parser(s) }
|
): ParserPair<*> = T::class with CommandArgParser { s: String, _: CommandSender -> parser(s) }
|
||||||
|
|
||||||
@ -173,7 +173,7 @@ class CommandParserContextBuilder : MutableList<ParserPair<*>> by mutableListOf(
|
|||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
@JvmSynthetic
|
@JvmSynthetic
|
||||||
@LowPriorityInOverloadResolution
|
@LowPriorityInOverloadResolution
|
||||||
inline infix fun <reified T : Any> add(
|
public inline infix fun <reified T : Any> add(
|
||||||
crossinline parser: CommandArgParser<*>.(s: String, sender: CommandSender) -> T
|
crossinline parser: CommandArgParser<*>.(s: String, sender: CommandSender) -> T
|
||||||
): ParserPair<*> = T::class with CommandArgParser(parser)
|
): ParserPair<*> = T::class with CommandArgParser(parser)
|
||||||
}
|
}
|
||||||
|
@ -14,4 +14,4 @@ import net.mamoe.mirai.event.Event
|
|||||||
/**
|
/**
|
||||||
* 表示来自 mirai-console 的事件
|
* 表示来自 mirai-console 的事件
|
||||||
*/
|
*/
|
||||||
interface ConsoleEvent : Event
|
public interface ConsoleEvent : Event
|
@ -22,15 +22,16 @@ import java.io.File
|
|||||||
*
|
*
|
||||||
* @see PluginLoader 插件加载器
|
* @see PluginLoader 插件加载器
|
||||||
*/
|
*/
|
||||||
interface Plugin {
|
public interface Plugin {
|
||||||
/**
|
/**
|
||||||
* 所属插件加载器实例, 此加载器必须能加载这个 [Plugin].
|
* 所属插件加载器实例, 此加载器必须能加载这个 [Plugin].
|
||||||
*/
|
*/
|
||||||
val loader: PluginLoader<*, *>
|
public val loader: PluginLoader<*, *>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:JvmSynthetic
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
inline val <P : Plugin> P.safeLoader: PluginLoader<P, PluginDescription>
|
public inline val <P : Plugin> P.safeLoader: PluginLoader<P, PluginDescription>
|
||||||
get() = this.loader as PluginLoader<P, PluginDescription>
|
get() = this.loader as PluginLoader<P, PluginDescription>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -39,15 +40,17 @@ inline val <P : Plugin> P.safeLoader: PluginLoader<P, PluginDescription>
|
|||||||
* @see JvmPlugin
|
* @see JvmPlugin
|
||||||
*/
|
*/
|
||||||
@ConsoleExperimentalAPI("classname is subject to change")
|
@ConsoleExperimentalAPI("classname is subject to change")
|
||||||
interface PluginFileExtensions {
|
public interface PluginFileExtensions {
|
||||||
/**
|
/**
|
||||||
* 数据目录
|
* 数据目录
|
||||||
*/
|
*/
|
||||||
val dataFolder: File
|
public val dataFolder: File
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 从数据目录获取一个文件, 若不存在则创建文件.
|
* 从数据目录获取一个文件, 若不存在则创建文件.
|
||||||
*/
|
*/
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
fun file(relativePath: String): File = File(dataFolder, relativePath).apply { createNewFile() }
|
public fun file(relativePath: String): File = File(dataFolder, relativePath).apply { createNewFile() }
|
||||||
|
|
||||||
|
// TODO: 2020/7/11 add `fun path(...): Path` ?
|
||||||
}
|
}
|
@ -7,7 +7,7 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("unused", "INAPPLICABLE_JVM_NAME")
|
@file:Suppress("unused", "INAPPLICABLE_JVM_NAME", "NOTHING_TO_INLINE")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.plugin
|
package net.mamoe.mirai.console.plugin
|
||||||
|
|
||||||
@ -23,11 +23,11 @@ import java.io.File
|
|||||||
*
|
*
|
||||||
* @see JarPluginLoader Jar 插件加载器
|
* @see JarPluginLoader Jar 插件加载器
|
||||||
*/
|
*/
|
||||||
interface PluginLoader<P : Plugin, D : PluginDescription> {
|
public interface PluginLoader<P : Plugin, D : PluginDescription> {
|
||||||
/**
|
/**
|
||||||
* 扫描并返回可以被加载的插件的 [描述][PluginDescription] 列表. 此函数只会被调用一次
|
* 扫描并返回可以被加载的插件的 [描述][PluginDescription] 列表. 此函数只会被调用一次
|
||||||
*/
|
*/
|
||||||
fun listPlugins(): List<D>
|
public fun listPlugins(): List<D>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取此插件的描述
|
* 获取此插件的描述
|
||||||
@ -36,7 +36,7 @@ interface PluginLoader<P : Plugin, D : PluginDescription> {
|
|||||||
*/
|
*/
|
||||||
@get:JvmName("getPluginDescription")
|
@get:JvmName("getPluginDescription")
|
||||||
@get:Throws(PluginLoadException::class)
|
@get:Throws(PluginLoadException::class)
|
||||||
val P.description: D
|
public val P.description: D // Java signature: `public P getDescription(P)`
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 加载一个插件 (实例), 但不 [启用][enable] 它. 返回加载成功的主类实例
|
* 加载一个插件 (实例), 但不 [启用][enable] 它. 返回加载成功的主类实例
|
||||||
@ -44,19 +44,20 @@ interface PluginLoader<P : Plugin, D : PluginDescription> {
|
|||||||
* @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如找不到主类等).
|
* @throws PluginLoadException 在加载插件遇到意料之中的错误时抛出 (如找不到主类等).
|
||||||
*/
|
*/
|
||||||
@Throws(PluginLoadException::class)
|
@Throws(PluginLoadException::class)
|
||||||
fun load(description: D): P
|
public fun load(description: D): P
|
||||||
|
|
||||||
fun enable(plugin: P)
|
public fun enable(plugin: P)
|
||||||
fun disable(plugin: P)
|
public fun disable(plugin: P)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <D : PluginDescription, P : Plugin> PluginLoader<P, D>.getDescription(plugin: P): D = plugin.description
|
public inline fun <D : PluginDescription, P : Plugin> PluginLoader<P, D>.getDescription(plugin: P): D =
|
||||||
|
plugin.description
|
||||||
|
|
||||||
open class PluginLoadException : RuntimeException {
|
public open class PluginLoadException : RuntimeException {
|
||||||
constructor() : super()
|
public constructor() : super()
|
||||||
constructor(message: String?) : super(message)
|
public constructor(message: String?) : super(message)
|
||||||
constructor(message: String?, cause: Throwable?) : super(message, cause)
|
public constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||||
constructor(cause: Throwable?) : super(cause)
|
public constructor(cause: Throwable?) : super(cause)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -65,18 +66,18 @@ open class PluginLoadException : RuntimeException {
|
|||||||
* @see AbstractFilePluginLoader 默认基础实现
|
* @see AbstractFilePluginLoader 默认基础实现
|
||||||
* @see JarPluginLoader 内建的 Jar (JVM) 插件加载器.
|
* @see JarPluginLoader 内建的 Jar (JVM) 插件加载器.
|
||||||
*/
|
*/
|
||||||
interface FilePluginLoader<P : Plugin, D : PluginDescription> : PluginLoader<P, D> {
|
public interface FilePluginLoader<P : Plugin, D : PluginDescription> : PluginLoader<P, D> {
|
||||||
/**
|
/**
|
||||||
* 所支持的插件文件后缀, 含 '.'. 如 [JarPluginLoader] 为 ".jar"
|
* 所支持的插件文件后缀, 含 '.'. 如 [JarPluginLoader] 为 ".jar"
|
||||||
*/
|
*/
|
||||||
val fileSuffix: String
|
public val fileSuffix: String
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* [FilePluginLoader] 的默认基础实现
|
* [FilePluginLoader] 的默认基础实现
|
||||||
*/
|
*/
|
||||||
abstract class AbstractFilePluginLoader<P : Plugin, D : PluginDescription>(
|
public abstract class AbstractFilePluginLoader<P : Plugin, D : PluginDescription>(
|
||||||
override val fileSuffix: String
|
public override val fileSuffix: String
|
||||||
) : FilePluginLoader<P, D> {
|
) : FilePluginLoader<P, D> {
|
||||||
private fun pluginsFilesSequence(): Sequence<File> =
|
private fun pluginsFilesSequence(): Sequence<File> =
|
||||||
PluginManager.pluginsDir.walk().filter { it.isFile && it.name.endsWith(fileSuffix, ignoreCase = true) }
|
PluginManager.pluginsDir.walk().filter { it.isFile && it.name.endsWith(fileSuffix, ignoreCase = true) }
|
||||||
@ -86,7 +87,7 @@ abstract class AbstractFilePluginLoader<P : Plugin, D : PluginDescription>(
|
|||||||
*/
|
*/
|
||||||
protected abstract fun Sequence<File>.mapToDescription(): List<D>
|
protected abstract fun Sequence<File>.mapToDescription(): List<D>
|
||||||
|
|
||||||
final override fun listPlugins(): List<D> = pluginsFilesSequence().mapToDescription()
|
public final override fun listPlugins(): List<D> = pluginsFilesSequence().mapToDescription()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,18 +18,68 @@ import net.mamoe.mirai.utils.info
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
|
||||||
val Plugin.description: PluginDescription
|
// TODO: 2020/7/11 top-level or in PluginManager.companion?
|
||||||
get() = PluginManager.resolvedPlugins.firstOrNull { it == this }?.loader?.cast<PluginLoader<Plugin, PluginDescription>>()
|
public val Plugin.description: PluginDescription
|
||||||
?.getDescription(
|
get() = PluginManagerImpl.resolvedPlugins.firstOrNull { it == this }
|
||||||
this
|
?.loader?.cast<PluginLoader<Plugin, PluginDescription>>()
|
||||||
) ?: error("Plugin is unloaded")
|
?.getDescription(this)
|
||||||
|
?: error("Plugin is unloaded")
|
||||||
|
|
||||||
inline fun PluginLoader<*, *>.register() = PluginManager.registerPluginLoader(this)
|
@JvmSynthetic
|
||||||
inline fun PluginLoader<*, *>.unregister() = PluginManager.unregisterPluginLoader(this)
|
public inline fun PluginLoader<*, *>.register(): Boolean = PluginManager.registerPluginLoader(this)
|
||||||
|
|
||||||
object PluginManager {
|
@JvmSynthetic
|
||||||
val pluginsDir = File(MiraiConsole.rootDir, "plugins").apply { mkdir() }
|
public inline fun PluginLoader<*, *>.unregister(): Boolean = PluginManager.unregisterPluginLoader(this)
|
||||||
val pluginsDataFolder = File(MiraiConsole.rootDir, "data").apply { mkdir() }
|
|
||||||
|
// TODO: 2020/7/11 document
|
||||||
|
public interface PluginManager {
|
||||||
|
public val pluginsDir: File
|
||||||
|
|
||||||
|
public val pluginsDataFolder: File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 已加载的插件列表
|
||||||
|
*/
|
||||||
|
public val plugins: List<Plugin>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 内建的插件加载器列表. 由 [MiraiConsole] 初始化
|
||||||
|
*/
|
||||||
|
public val builtInLoaders: List<PluginLoader<*, *>>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 由插件创建的 [PluginLoader]
|
||||||
|
*/
|
||||||
|
public val pluginLoaders: List<PluginLoader<*, *>>
|
||||||
|
|
||||||
|
public fun registerPluginLoader(loader: PluginLoader<*, *>): Boolean
|
||||||
|
|
||||||
|
public fun unregisterPluginLoader(loader: PluginLoader<*, *>): Boolean
|
||||||
|
|
||||||
|
public companion object INSTANCE : PluginManager by PluginManagerImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
public class PluginMissingDependencyException : PluginResolutionException {
|
||||||
|
public constructor() : super()
|
||||||
|
public constructor(message: String?) : super(message)
|
||||||
|
public constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||||
|
public constructor(cause: Throwable?) : super(cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
public open class PluginResolutionException : Exception {
|
||||||
|
public constructor() : super()
|
||||||
|
public constructor(message: String?) : super(message)
|
||||||
|
public constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||||
|
public constructor(cause: Throwable?) : super(cause)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal
|
||||||
|
|
||||||
|
|
||||||
|
internal object PluginManagerImpl : PluginManager {
|
||||||
|
override val pluginsDir = File(MiraiConsole.rootDir, "plugins").apply { mkdir() }
|
||||||
|
override val pluginsDataFolder = File(MiraiConsole.rootDir, "data").apply { mkdir() }
|
||||||
|
|
||||||
@Suppress("ObjectPropertyName")
|
@Suppress("ObjectPropertyName")
|
||||||
private val _pluginLoaders: MutableList<PluginLoader<*, *>> = mutableListOf()
|
private val _pluginLoaders: MutableList<PluginLoader<*, *>> = mutableListOf()
|
||||||
@ -38,38 +88,21 @@ object PluginManager {
|
|||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
internal val resolvedPlugins: MutableList<Plugin> = mutableListOf()
|
internal val resolvedPlugins: MutableList<Plugin> = mutableListOf()
|
||||||
|
override val plugins: List<Plugin>
|
||||||
/**
|
|
||||||
* 已加载的插件列表
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
val plugins: List<Plugin>
|
|
||||||
get() = resolvedPlugins.toList()
|
get() = resolvedPlugins.toList()
|
||||||
|
override val builtInLoaders: List<PluginLoader<*, *>>
|
||||||
/**
|
|
||||||
* 内建的插件加载器列表. 由 [MiraiConsole] 初始化
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
val builtInLoaders: List<PluginLoader<*, *>>
|
|
||||||
get() = MiraiConsole.builtInPluginLoaders
|
get() = MiraiConsole.builtInPluginLoaders
|
||||||
|
override val pluginLoaders: List<PluginLoader<*, *>>
|
||||||
/**
|
|
||||||
* 由插件创建的 [PluginLoader]
|
|
||||||
*/
|
|
||||||
@JvmStatic
|
|
||||||
val pluginLoaders: List<PluginLoader<*, *>>
|
|
||||||
get() = _pluginLoaders.toList()
|
get() = _pluginLoaders.toList()
|
||||||
|
|
||||||
@JvmStatic
|
override fun registerPluginLoader(loader: PluginLoader<*, *>): Boolean = loadersLock.withLock {
|
||||||
fun registerPluginLoader(loader: PluginLoader<*, *>): Boolean = loadersLock.withLock {
|
|
||||||
if (_pluginLoaders.any { it::class == loader }) {
|
if (_pluginLoaders.any { it::class == loader }) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
_pluginLoaders.add(loader)
|
_pluginLoaders.add(loader)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
override fun unregisterPluginLoader(loader: PluginLoader<*, *>) = loadersLock.withLock {
|
||||||
fun unregisterPluginLoader(loader: PluginLoader<*, *>) = loadersLock.withLock {
|
|
||||||
_pluginLoaders.remove(loader)
|
_pluginLoaders.remove(loader)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,8 +210,10 @@ object PluginManager {
|
|||||||
this.consumeLoadable().also { resultPlugins ->
|
this.consumeLoadable().also { resultPlugins ->
|
||||||
check(resultPlugins.size < beforeSize) {
|
check(resultPlugins.size < beforeSize) {
|
||||||
throw PluginMissingDependencyException(resultPlugins.joinToString("\n") { badPlugin ->
|
throw PluginMissingDependencyException(resultPlugins.joinToString("\n") { badPlugin ->
|
||||||
"Cannot load plugin ${badPlugin.name}, missing dependencies: ${badPlugin.dependencies.filterIsMissing()
|
"Cannot load plugin ${badPlugin.name}, missing dependencies: ${
|
||||||
.joinToString()}"
|
badPlugin.dependencies.filterIsMissing()
|
||||||
|
.joinToString()
|
||||||
|
}"
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}.doSort()
|
}.doSort()
|
||||||
@ -191,16 +226,6 @@ object PluginManager {
|
|||||||
// endregion
|
// endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
class PluginMissingDependencyException(message: String?) : PluginResolutionException(message)
|
|
||||||
|
|
||||||
open class PluginResolutionException : Exception {
|
|
||||||
constructor() : super()
|
|
||||||
constructor(message: String?) : super(message)
|
|
||||||
constructor(message: String?, cause: Throwable?) : super(message, cause)
|
|
||||||
constructor(cause: Throwable?) : super(cause)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal data class PluginDescriptionWithLoader(
|
internal data class PluginDescriptionWithLoader(
|
||||||
@JvmField val loader: PluginLoader<*, PluginDescription>, // easier type
|
@JvmField val loader: PluginLoader<*, PluginDescription>, // easier type
|
||||||
@JvmField val delegate: PluginDescription
|
@JvmField val delegate: PluginDescription
|
||||||
|
@ -15,10 +15,11 @@ import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
interface PluginCenter {
|
public interface PluginCenter {
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PluginInsight(
|
@ConsoleExperimentalAPI
|
||||||
|
public data class PluginInsight(
|
||||||
val name: String,
|
val name: String,
|
||||||
val version: String,
|
val version: String,
|
||||||
@SerialName("core")
|
@SerialName("core")
|
||||||
@ -31,8 +32,9 @@ interface PluginCenter {
|
|||||||
val commands: List<String>
|
val commands: List<String>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PluginInfo(
|
public data class PluginInfo(
|
||||||
val name: String,
|
val name: String,
|
||||||
val version: String,
|
val version: String,
|
||||||
@SerialName("core")
|
@SerialName("core")
|
||||||
@ -54,24 +56,24 @@ interface PluginCenter {
|
|||||||
* 能获取到多少由实际的 [PluginCenter] 决定
|
* 能获取到多少由实际的 [PluginCenter] 决定
|
||||||
* 返回 插件名->Insight
|
* 返回 插件名->Insight
|
||||||
*/
|
*/
|
||||||
suspend fun fetchPlugin(page: Int): Map<String, PluginInsight>
|
public suspend fun fetchPlugin(page: Int): Map<String, PluginInsight>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 尝试获取到某个插件 by 全名, case sensitive
|
* 尝试获取到某个插件 by 全名, case sensitive
|
||||||
* null 则没有
|
* null 则没有
|
||||||
*/
|
*/
|
||||||
suspend fun findPlugin(name: String): PluginInfo?
|
public suspend fun findPlugin(name: String): PluginInfo?
|
||||||
|
|
||||||
|
|
||||||
suspend fun <T : Any> T.downloadPlugin(name: String, progressListener: T.(Float) -> Unit): File
|
public suspend fun <T : Any> T.downloadPlugin(name: String, progressListener: T.(Float) -> Unit): File
|
||||||
|
|
||||||
suspend fun downloadPlugin(name: String, progressListener: PluginCenter.(Float) -> Unit): File =
|
public suspend fun downloadPlugin(name: String, progressListener: PluginCenter.(Float) -> Unit): File =
|
||||||
downloadPlugin<PluginCenter>(name, progressListener)
|
downloadPlugin<PluginCenter>(name, progressListener)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新
|
* 刷新
|
||||||
*/
|
*/
|
||||||
suspend fun refresh()
|
public suspend fun refresh()
|
||||||
|
|
||||||
val name: String
|
public val name: String
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,8 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.plugin
|
package net.mamoe.mirai.console.plugin
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
import net.mamoe.mirai.console.setting.internal.map
|
import net.mamoe.mirai.console.setting.internal.map
|
||||||
import net.mamoe.yamlkt.Yaml
|
import net.mamoe.yamlkt.Yaml
|
||||||
@ -19,14 +20,14 @@ import java.io.File
|
|||||||
|
|
||||||
/** 插件类型 */
|
/** 插件类型 */
|
||||||
@Serializable(with = PluginKind.AsStringSerializer::class)
|
@Serializable(with = PluginKind.AsStringSerializer::class)
|
||||||
enum class PluginKind {
|
public enum class PluginKind {
|
||||||
/** 表示此插件提供一个 [PluginLoader], 应在加载其他 [NORMAL] 类型插件前加载 */
|
/** 表示此插件提供一个 [PluginLoader], 应在加载其他 [NORMAL] 类型插件前加载 */
|
||||||
LOADER,
|
LOADER,
|
||||||
|
|
||||||
/** 表示此插件为一个通常的插件, 按照正常的依赖关系加载. */
|
/** 表示此插件为一个通常的插件, 按照正常的依赖关系加载. */
|
||||||
NORMAL;
|
NORMAL;
|
||||||
|
|
||||||
object AsStringSerializer : KSerializer<PluginKind> by String.serializer().map(
|
public object AsStringSerializer : KSerializer<PluginKind> by String.serializer().map(
|
||||||
serializer = { it.name },
|
serializer = { it.name },
|
||||||
deserializer = { str ->
|
deserializer = { str ->
|
||||||
values().firstOrNull {
|
values().firstOrNull {
|
||||||
@ -39,38 +40,38 @@ enum class PluginKind {
|
|||||||
/**
|
/**
|
||||||
* 插件描述
|
* 插件描述
|
||||||
*/
|
*/
|
||||||
interface PluginDescription {
|
public interface PluginDescription {
|
||||||
val kind: PluginKind
|
public val kind: PluginKind
|
||||||
|
|
||||||
val name: String
|
public val name: String
|
||||||
val author: String
|
public val author: String
|
||||||
val version: String
|
public val version: String
|
||||||
val info: String
|
public val info: String
|
||||||
|
|
||||||
/** 此插件依赖的其他插件, 将会在这些插件加载之后加载此插件 */
|
/** 此插件依赖的其他插件, 将会在这些插件加载之后加载此插件 */
|
||||||
val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency>
|
public val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency>
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 插件的一个依赖的信息 */
|
/** 插件的一个依赖的信息 */
|
||||||
@Serializable
|
@Serializable
|
||||||
data class PluginDependency(
|
public data class PluginDependency(
|
||||||
/** 依赖插件名 */
|
/** 依赖插件名 */
|
||||||
val name: String,
|
public val name: String,
|
||||||
/**
|
/**
|
||||||
* 依赖版本号. 为 null 时则为不限制版本.
|
* 依赖版本号. 为 null 时则为不限制版本.
|
||||||
* @see versionKind 版本号类型
|
* @see versionKind 版本号类型
|
||||||
*/
|
*/
|
||||||
val version: String? = null,
|
public val version: String? = null,
|
||||||
/** 版本号类型 */
|
/** 版本号类型 */
|
||||||
val versionKind: VersionKind = VersionKind.AT_LEAST,
|
public val versionKind: VersionKind = VersionKind.AT_LEAST,
|
||||||
/**
|
/**
|
||||||
* 若为 `false`, 插件在找不到此依赖时也能正常加载.
|
* 若为 `false`, 插件在找不到此依赖时也能正常加载.
|
||||||
*/
|
*/
|
||||||
val isOptional: Boolean = false
|
public val isOptional: Boolean = false
|
||||||
) {
|
) {
|
||||||
/** 版本号类型 */
|
/** 版本号类型 */
|
||||||
@Serializable(with = VersionKind.AsStringSerializer::class)
|
@Serializable(with = VersionKind.AsStringSerializer::class)
|
||||||
enum class VersionKind(
|
public enum class VersionKind(
|
||||||
private vararg val serialNames: String
|
private vararg val serialNames: String
|
||||||
) {
|
) {
|
||||||
/** 要求依赖精确的版本 */
|
/** 要求依赖精确的版本 */
|
||||||
@ -82,7 +83,7 @@ data class PluginDependency(
|
|||||||
/** 要求依赖最高版本 */
|
/** 要求依赖最高版本 */
|
||||||
AT_MOST("at_most", "AtMost", "most", "highest", "-");
|
AT_MOST("at_most", "AtMost", "most", "highest", "-");
|
||||||
|
|
||||||
object AsStringSerializer : KSerializer<VersionKind> by String.serializer().map(
|
public object AsStringSerializer : KSerializer<VersionKind> by String.serializer().map(
|
||||||
serializer = { it.serialNames.first() },
|
serializer = { it.serialNames.first() },
|
||||||
deserializer = { str ->
|
deserializer = { str ->
|
||||||
values().firstOrNull {
|
values().firstOrNull {
|
||||||
@ -92,7 +93,7 @@ data class PluginDependency(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toString(): String {
|
public override fun toString(): String {
|
||||||
return "$name ${versionKind.toEnglishString()}v$version"
|
return "$name ${versionKind.toEnglishString()}v$version"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +101,7 @@ data class PluginDependency(
|
|||||||
/**
|
/**
|
||||||
* 可支持解析 [String] 作为 [PluginDependency.version] 或单个 [PluginDependency]
|
* 可支持解析 [String] 作为 [PluginDependency.version] 或单个 [PluginDependency]
|
||||||
*/
|
*/
|
||||||
object SmartSerializer : KSerializer<PluginDependency> by YamlDynamicSerializer.map(
|
public object SmartSerializer : KSerializer<PluginDependency> by YamlDynamicSerializer.map(
|
||||||
serializer = { it },
|
serializer = { it },
|
||||||
deserializer = { any ->
|
deserializer = { any ->
|
||||||
when (any) {
|
when (any) {
|
||||||
@ -112,10 +113,10 @@ data class PluginDependency(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于文件的插件的描述
|
* 基于文件的插件 的描述
|
||||||
*/
|
*/
|
||||||
interface FilePluginDescription : PluginDescription {
|
public interface FilePluginDescription : PluginDescription {
|
||||||
val file: File
|
public val file: File
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun PluginDependency.VersionKind.toEnglishString(): String = when (this) {
|
internal fun PluginDependency.VersionKind.toEnglishString(): String = when (this) {
|
||||||
|
@ -39,8 +39,8 @@ internal abstract class JvmPluginInternal(
|
|||||||
) : JvmPlugin,
|
) : JvmPlugin,
|
||||||
CoroutineScope {
|
CoroutineScope {
|
||||||
|
|
||||||
private val resourceConsoleDelegate by lazy { this::class.asResourceContainer() }
|
private val resourceContainerDelegate by lazy { this::class.asResourceContainer() }
|
||||||
override fun getResourceAsStream(name: String): InputStream = resourceConsoleDelegate.getResourceAsStream(name)
|
override fun getResourceAsStream(name: String): InputStream = resourceContainerDelegate.getResourceAsStream(name)
|
||||||
|
|
||||||
// region JvmPlugin
|
// region JvmPlugin
|
||||||
/**
|
/**
|
||||||
|
@ -22,10 +22,10 @@ import kotlin.coroutines.EmptyCoroutineContext
|
|||||||
* @see JavaPlugin
|
* @see JavaPlugin
|
||||||
* @see KotlinPlugin
|
* @see KotlinPlugin
|
||||||
*/
|
*/
|
||||||
abstract class AbstractJvmPlugin @JvmOverloads constructor(
|
public abstract class AbstractJvmPlugin @JvmOverloads constructor(
|
||||||
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||||
) : JvmPlugin, JvmPluginInternal(parentCoroutineContext) {
|
) : JvmPlugin, JvmPluginInternal(parentCoroutineContext) {
|
||||||
final override val name: String get() = this.description.name
|
public final override val name: String get() = this.description.name
|
||||||
|
|
||||||
override fun <T : Setting> getSetting(clazz: Class<T>): T = loader.settingStorage.load(this, clazz)
|
public override fun <T : Setting> getSetting(clazz: Class<T>): T = loader.settingStorage.load(this, clazz)
|
||||||
}
|
}
|
@ -13,6 +13,7 @@ import kotlinx.coroutines.*
|
|||||||
import net.mamoe.mirai.console.MiraiConsole
|
import net.mamoe.mirai.console.MiraiConsole
|
||||||
import net.mamoe.mirai.console.MiraiConsoleInternal
|
import net.mamoe.mirai.console.MiraiConsoleInternal
|
||||||
import net.mamoe.mirai.console.plugin.AbstractFilePluginLoader
|
import net.mamoe.mirai.console.plugin.AbstractFilePluginLoader
|
||||||
|
import net.mamoe.mirai.console.plugin.FilePluginLoader
|
||||||
import net.mamoe.mirai.console.plugin.PluginLoadException
|
import net.mamoe.mirai.console.plugin.PluginLoadException
|
||||||
import net.mamoe.mirai.console.plugin.internal.JvmPluginInternal
|
import net.mamoe.mirai.console.plugin.internal.JvmPluginInternal
|
||||||
import net.mamoe.mirai.console.plugin.internal.PluginsLoader
|
import net.mamoe.mirai.console.plugin.internal.PluginsLoader
|
||||||
@ -28,11 +29,24 @@ import kotlin.reflect.full.createInstance
|
|||||||
/**
|
/**
|
||||||
* 内建的 Jar (JVM) 插件加载器
|
* 内建的 Jar (JVM) 插件加载器
|
||||||
*/
|
*/
|
||||||
object JarPluginLoader : AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"), CoroutineScope {
|
public interface JarPluginLoader : CoroutineScope, FilePluginLoader<JvmPlugin, JvmPluginDescription> {
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
|
public val settingStorage: SettingStorage
|
||||||
|
|
||||||
|
public companion object INSTANCE : JarPluginLoader by JarPluginLoaderImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal object JarPluginLoaderImpl :
|
||||||
|
AbstractFilePluginLoader<JvmPlugin, JvmPluginDescription>(".jar"),
|
||||||
|
CoroutineScope,
|
||||||
|
JarPluginLoader {
|
||||||
|
|
||||||
private val logger: MiraiLogger = MiraiConsole.newLogger(JarPluginLoader::class.simpleName!!)
|
private val logger: MiraiLogger = MiraiConsole.newLogger(JarPluginLoader::class.simpleName!!)
|
||||||
|
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
val settingStorage: SettingStorage = MiraiConsoleInternal.settingStorage
|
override val settingStorage: SettingStorage
|
||||||
|
get() = MiraiConsoleInternal.settingStorage
|
||||||
|
|
||||||
override val coroutineContext: CoroutineContext =
|
override val coroutineContext: CoroutineContext =
|
||||||
MiraiConsole.coroutineContext +
|
MiraiConsole.coroutineContext +
|
||||||
|
@ -18,14 +18,12 @@ import kotlin.coroutines.EmptyCoroutineContext
|
|||||||
/**
|
/**
|
||||||
* Java 插件的父类
|
* Java 插件的父类
|
||||||
*/
|
*/
|
||||||
abstract class JavaPlugin @JvmOverloads constructor(
|
public abstract class JavaPlugin @JvmOverloads constructor(
|
||||||
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||||
) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext) {
|
) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Java API Scheduler
|
* Java API Scheduler
|
||||||
*/
|
*/
|
||||||
val scheduler: JavaPluginScheduler =
|
public val scheduler: JavaPluginScheduler = JavaPluginScheduler(this.coroutineContext)
|
||||||
JavaPluginScheduler(this.coroutineContext)
|
|
||||||
}
|
}
|
@ -7,7 +7,7 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS")
|
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS", "NOTHING_TO_INLINE")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.plugin.jvm
|
package net.mamoe.mirai.console.plugin.jvm
|
||||||
|
|
||||||
@ -32,34 +32,39 @@ import kotlin.reflect.KClass
|
|||||||
* @see JvmPlugin 支持文件系统扩展
|
* @see JvmPlugin 支持文件系统扩展
|
||||||
* @see ResourceContainer 支持资源获取 (如 Jar 中的资源文件)
|
* @see ResourceContainer 支持资源获取 (如 Jar 中的资源文件)
|
||||||
*/
|
*/
|
||||||
interface JvmPlugin : Plugin, CoroutineScope, PluginFileExtensions, ResourceContainer, AutoSaveSettingHolder {
|
public interface JvmPlugin : Plugin, CoroutineScope,
|
||||||
|
PluginFileExtensions, ResourceContainer, AutoSaveSettingHolder {
|
||||||
/** 日志 */
|
/** 日志 */
|
||||||
val logger: MiraiLogger
|
public val logger: MiraiLogger
|
||||||
|
|
||||||
/** 插件描述 */
|
/** 插件描述 */
|
||||||
val description: JvmPluginDescription
|
public val description: JvmPluginDescription
|
||||||
|
|
||||||
/** 所属插件加载器实例 */
|
/** 所属插件加载器实例 */
|
||||||
override val loader: JarPluginLoader get() = JarPluginLoader
|
public override val loader: JarPluginLoader get() = JarPluginLoader
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取一个 [Setting] 实例
|
* 获取一个 [Setting] 实例
|
||||||
*/
|
*/
|
||||||
fun <T : Setting> getSetting(clazz: Class<T>): T
|
public fun <T : Setting> getSetting(clazz: Class<T>): T
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: 2020/7/11 document onLoad, onEnable, onDisable
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
fun onLoad() {
|
public fun onLoad() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
fun onEnable() {
|
public fun onEnable() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
fun onDisable() {
|
public fun onDisable() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Setting> JvmPlugin.getSetting(clazz: KClass<T>) = this.getSetting(clazz.java)
|
@JvmSynthetic
|
||||||
inline fun <reified T : Setting> JvmPlugin.getSetting() = this.getSetting(T::class)
|
public inline fun <T : Setting> JvmPlugin.getSetting(clazz: KClass<T>): T = this.getSetting(clazz.java)
|
||||||
|
|
||||||
|
@JvmSynthetic
|
||||||
|
public inline fun <reified T : Setting> JvmPlugin.getSetting(): T = this.getSetting(T::class)
|
@ -19,23 +19,23 @@ import net.mamoe.mirai.console.plugin.PluginKind
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class JvmPluginDescription internal constructor(
|
public class JvmPluginDescription internal constructor(
|
||||||
override val kind: PluginKind = PluginKind.NORMAL,
|
public override val kind: PluginKind = PluginKind.NORMAL,
|
||||||
override val name: String,
|
public override val name: String,
|
||||||
@SerialName("main")
|
@SerialName("main")
|
||||||
val mainClassName: String,
|
public val mainClassName: String,
|
||||||
override val author: String = "",
|
public override val author: String = "",
|
||||||
override val version: String,
|
public override val version: String,
|
||||||
override val info: String = "",
|
public override val info: String = "",
|
||||||
@SerialName("depends")
|
@SerialName("depends")
|
||||||
override val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> = listOf()
|
public override val dependencies: List<@Serializable(with = PluginDependency.SmartSerializer::class) PluginDependency> = listOf()
|
||||||
) : PluginDescription, FilePluginDescription {
|
) : PluginDescription, FilePluginDescription {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 在手动实现时使用这个构造器.
|
* 在手动实现时使用这个构造器.
|
||||||
*/
|
*/
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
constructor(
|
public constructor(
|
||||||
kind: PluginKind, name: String, mainClassName: String, author: String,
|
kind: PluginKind, name: String, mainClassName: String, author: String,
|
||||||
version: String, info: String, depends: List<PluginDependency>,
|
version: String, info: String, depends: List<PluginDependency>,
|
||||||
file: File
|
file: File
|
||||||
@ -43,7 +43,7 @@ class JvmPluginDescription internal constructor(
|
|||||||
this._file = file
|
this._file = file
|
||||||
}
|
}
|
||||||
|
|
||||||
override val file: File
|
public override val file: File
|
||||||
get() = _file ?: error("Internal error: JvmPluginDescription(name=$name)._file == null")
|
get() = _file ?: error("Internal error: JvmPluginDescription(name=$name)._file == null")
|
||||||
|
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ class JvmPluginDescription internal constructor(
|
|||||||
@JvmField
|
@JvmField
|
||||||
internal var _file: File? = null
|
internal var _file: File? = null
|
||||||
|
|
||||||
override fun toString(): String {
|
public override fun toString(): String {
|
||||||
return "JvmPluginDescription(kind=$kind, name='$name', mainClassName='$mainClassName', author='$author', version='$version', info='$info', dependencies=$dependencies, _file=$_file)"
|
return "JvmPluginDescription(kind=$kind, name='$name', mainClassName='$mainClassName', author='$author', version='$version', info='$info', dependencies=$dependencies, _file=$_file)"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,13 +7,10 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS")
|
@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "EXPOSED_SUPER_CLASS", "RedundantVisibilityModifier")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.plugin.jvm
|
package net.mamoe.mirai.console.plugin.jvm
|
||||||
|
|
||||||
import net.mamoe.mirai.console.setting.Setting
|
|
||||||
import net.mamoe.mirai.console.setting.getValue
|
|
||||||
import net.mamoe.mirai.console.setting.value
|
|
||||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||||
import kotlin.coroutines.CoroutineContext
|
import kotlin.coroutines.CoroutineContext
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
import kotlin.coroutines.EmptyCoroutineContext
|
||||||
@ -23,7 +20,7 @@ import kotlin.coroutines.EmptyCoroutineContext
|
|||||||
*
|
*
|
||||||
* 必须通过 "plugin.yml" 指定主类并由 [JarPluginLoader] 加载.
|
* 必须通过 "plugin.yml" 指定主类并由 [JarPluginLoader] 加载.
|
||||||
*/
|
*/
|
||||||
abstract class KotlinPlugin @JvmOverloads constructor(
|
public abstract class KotlinPlugin @JvmOverloads constructor(
|
||||||
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||||
) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext)
|
) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext)
|
||||||
|
|
||||||
@ -32,11 +29,11 @@ abstract class KotlinPlugin @JvmOverloads constructor(
|
|||||||
* 在内存动态加载的插件.
|
* 在内存动态加载的插件.
|
||||||
*/
|
*/
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
abstract class KotlinMemoryPlugin @JvmOverloads constructor(
|
public abstract class KotlinMemoryPlugin @JvmOverloads constructor(
|
||||||
description: JvmPluginDescription,
|
description: JvmPluginDescription,
|
||||||
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
parentCoroutineContext: CoroutineContext = EmptyCoroutineContext
|
||||||
) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext) {
|
) : JvmPlugin, AbstractJvmPlugin(parentCoroutineContext) {
|
||||||
final override var _description: JvmPluginDescription
|
internal final override var _description: JvmPluginDescription
|
||||||
get() = super._description
|
get() = super._description
|
||||||
set(value) {
|
set(value) {
|
||||||
super._description = value
|
super._description = value
|
||||||
@ -47,8 +44,11 @@ abstract class KotlinMemoryPlugin @JvmOverloads constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
object MyPlugin : KotlinPlugin()
|
/*
|
||||||
|
|
||||||
object AccountSetting : Setting by MyPlugin.getSetting() {
|
public object MyPlugin : KotlinPlugin()
|
||||||
val s by value(1)
|
|
||||||
}
|
public object AccountSetting : Setting by MyPlugin.getSetting() {
|
||||||
|
public val s by value(1)
|
||||||
|
}
|
||||||
|
*/
|
@ -29,11 +29,11 @@ import kotlin.reflect.KType
|
|||||||
* ```
|
* ```
|
||||||
*/
|
*/
|
||||||
// TODO: 2020/6/26 document
|
// TODO: 2020/6/26 document
|
||||||
typealias SerialName = kotlinx.serialization.SerialName
|
public typealias SerialName = kotlinx.serialization.SerialName
|
||||||
|
|
||||||
// TODO: 2020/6/26 document
|
// TODO: 2020/6/26 document
|
||||||
abstract class AbstractSetting : Setting, SettingImpl() {
|
public abstract class AbstractSetting : Setting, SettingImpl() {
|
||||||
final override operator fun <T> SerializerAwareValue<T>.provideDelegate(
|
public final override operator fun <T> SerializerAwareValue<T>.provideDelegate(
|
||||||
thisRef: Any?,
|
thisRef: Any?,
|
||||||
property: KProperty<*>
|
property: KProperty<*>
|
||||||
): SerializerAwareValue<T> {
|
): SerializerAwareValue<T> {
|
||||||
@ -42,34 +42,34 @@ abstract class AbstractSetting : Setting, SettingImpl() {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
final override val updaterSerializer: KSerializer<Unit> get() = super.updaterSerializer
|
public final override val updaterSerializer: KSerializer<Unit> get() = super.updaterSerializer
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: 2020/6/26 document
|
// TODO: 2020/6/26 document
|
||||||
interface Setting {
|
public interface Setting {
|
||||||
// TODO: 2020/6/26 document
|
// TODO: 2020/6/26 document
|
||||||
operator fun <T> SerializerAwareValue<T>.provideDelegate(
|
public operator fun <T> SerializerAwareValue<T>.provideDelegate(
|
||||||
thisRef: Any?,
|
thisRef: Any?,
|
||||||
property: KProperty<*>
|
property: KProperty<*>
|
||||||
): SerializerAwareValue<T>
|
): SerializerAwareValue<T>
|
||||||
|
|
||||||
// TODO: 2020/6/26 document
|
// TODO: 2020/6/26 document
|
||||||
val updaterSerializer: KSerializer<Unit>
|
public val updaterSerializer: KSerializer<Unit>
|
||||||
|
|
||||||
fun onValueChanged(value: Value<*>)
|
public fun onValueChanged(value: Value<*>)
|
||||||
}
|
}
|
||||||
|
|
||||||
//// region Setting_value_primitives CODEGEN ////
|
//// region Setting_value_primitives CODEGEN ////
|
||||||
|
|
||||||
fun Setting.value(default: Byte): SerializerAwareValue<Byte> = valueImpl(default)
|
public fun Setting.value(default: Byte): SerializerAwareValue<Byte> = valueImpl(default)
|
||||||
fun Setting.value(default: Short): SerializerAwareValue<Short> = valueImpl(default)
|
public fun Setting.value(default: Short): SerializerAwareValue<Short> = valueImpl(default)
|
||||||
fun Setting.value(default: Int): SerializerAwareValue<Int> = valueImpl(default)
|
public fun Setting.value(default: Int): SerializerAwareValue<Int> = valueImpl(default)
|
||||||
fun Setting.value(default: Long): SerializerAwareValue<Long> = valueImpl(default)
|
public fun Setting.value(default: Long): SerializerAwareValue<Long> = valueImpl(default)
|
||||||
fun Setting.value(default: Float): SerializerAwareValue<Float> = valueImpl(default)
|
public fun Setting.value(default: Float): SerializerAwareValue<Float> = valueImpl(default)
|
||||||
fun Setting.value(default: Double): SerializerAwareValue<Double> = valueImpl(default)
|
public fun Setting.value(default: Double): SerializerAwareValue<Double> = valueImpl(default)
|
||||||
fun Setting.value(default: Char): SerializerAwareValue<Char> = valueImpl(default)
|
public fun Setting.value(default: Char): SerializerAwareValue<Char> = valueImpl(default)
|
||||||
fun Setting.value(default: Boolean): SerializerAwareValue<Boolean> = valueImpl(default)
|
public fun Setting.value(default: Boolean): SerializerAwareValue<Boolean> = valueImpl(default)
|
||||||
fun Setting.value(default: String): SerializerAwareValue<String> = valueImpl(default)
|
public fun Setting.value(default: String): SerializerAwareValue<String> = valueImpl(default)
|
||||||
|
|
||||||
//// endregion Setting_value_primitives CODEGEN ////
|
//// endregion Setting_value_primitives CODEGEN ////
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ fun Setting.value(default: String): SerializerAwareValue<String> = valueImpl(def
|
|||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
@LowPriorityInOverloadResolution
|
@LowPriorityInOverloadResolution
|
||||||
inline fun <reified T> Setting.value(default: T): SerializerAwareValue<T> = valueFromKType(typeOf0<T>(), default)
|
public inline fun <reified T> Setting.value(default: T): SerializerAwareValue<T> = valueFromKType(typeOf0<T>(), default)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a [Value] with reified type, and set default value by reflection to its no-arg public constructor.
|
* Creates a [Value] with reified type, and set default value by reflection to its no-arg public constructor.
|
||||||
@ -95,13 +95,13 @@ inline fun <reified T> Setting.value(default: T): SerializerAwareValue<T> = valu
|
|||||||
* (typically annotated with [kotlinx.serialization.Serializable])
|
* (typically annotated with [kotlinx.serialization.Serializable])
|
||||||
*/
|
*/
|
||||||
@LowPriorityInOverloadResolution
|
@LowPriorityInOverloadResolution
|
||||||
inline fun <reified T> Setting.value(): SerializerAwareValue<T> = value(T::class.createInstance() as T)
|
public inline fun <reified T> Setting.value(): SerializerAwareValue<T> = value(T::class.createInstance() as T)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a [Value] with specified [KType], and set default value.
|
* Creates a [Value] with specified [KType], and set default value.
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <T> Setting.valueFromKType(type: KType, default: T): SerializerAwareValue<T> =
|
public fun <T> Setting.valueFromKType(type: KType, default: T): SerializerAwareValue<T> =
|
||||||
(valueFromKTypeImpl(type) as SerializerAwareValue<Any?>).apply { this.value = default } as SerializerAwareValue<T>
|
(valueFromKTypeImpl(type) as SerializerAwareValue<Any?>).apply { this.value = default } as SerializerAwareValue<T>
|
||||||
|
|
||||||
// TODO: 2020/6/24 Introduce class TypeToken for compound types for Java.
|
// TODO: 2020/6/24 Introduce class TypeToken for compound types for Java.
|
@ -1,3 +1,5 @@
|
|||||||
|
@file:Suppress("NOTHING_TO_INLINE")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.setting
|
package net.mamoe.mirai.console.setting
|
||||||
|
|
||||||
import kotlinx.atomicfu.atomic
|
import kotlinx.atomicfu.atomic
|
||||||
@ -22,19 +24,20 @@ import kotlin.reflect.full.findAnnotation
|
|||||||
/**
|
/**
|
||||||
* [Setting] 存储容器
|
* [Setting] 存储容器
|
||||||
*/
|
*/
|
||||||
interface SettingStorage {
|
public interface SettingStorage {
|
||||||
/**
|
/**
|
||||||
* 读取一个实例
|
* 读取一个实例
|
||||||
*/
|
*/
|
||||||
fun <T : Setting> load(holder: SettingHolder, settingClass: Class<T>): T
|
public fun <T : Setting> load(holder: SettingHolder, settingClass: Class<T>): T
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存一个实例
|
* 保存一个实例
|
||||||
*/
|
*/
|
||||||
fun store(holder: SettingHolder, setting: Setting)
|
public fun store(holder: SettingHolder, setting: Setting)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Setting> SettingStorage.load(holder: SettingHolder, settingClass: KClass<T>): T =
|
// TODO: 2020/7/11 here or companion?
|
||||||
|
public inline fun <T : Setting> SettingStorage.load(holder: SettingHolder, settingClass: KClass<T>): T =
|
||||||
this.load(holder, settingClass.java)
|
this.load(holder, settingClass.java)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,17 +48,19 @@ fun <T : Setting> SettingStorage.load(holder: SettingHolder, settingClass: KClas
|
|||||||
*
|
*
|
||||||
* @see AutoSaveSettingHolder 自动保存
|
* @see AutoSaveSettingHolder 自动保存
|
||||||
*/
|
*/
|
||||||
interface SettingHolder {
|
public interface SettingHolder {
|
||||||
/**
|
/**
|
||||||
* 保存时使用的分类名
|
* 保存时使用的分类名
|
||||||
*/
|
*/
|
||||||
val name: String
|
public val name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 可以持有相关 [AutoSaveSetting] 的对象.
|
* 可以持有相关 [AutoSaveSetting] 的对象.
|
||||||
|
*
|
||||||
|
* @see net.mamoe.mirai.console.plugin.jvm.JvmPlugin
|
||||||
*/
|
*/
|
||||||
interface AutoSaveSettingHolder : SettingHolder, CoroutineScope {
|
public interface AutoSaveSettingHolder : SettingHolder, CoroutineScope {
|
||||||
/**
|
/**
|
||||||
* [AutoSaveSetting] 每次自动保存时间间隔
|
* [AutoSaveSetting] 每次自动保存时间间隔
|
||||||
*
|
*
|
||||||
@ -63,8 +68,11 @@ interface AutoSaveSettingHolder : SettingHolder, CoroutineScope {
|
|||||||
* - 区间的右端点为最大间隔, 一个 [Value] 被修改后, 最多不超过这个时间段后就会被保存.
|
* - 区间的右端点为最大间隔, 一个 [Value] 被修改后, 最多不超过这个时间段后就会被保存.
|
||||||
*
|
*
|
||||||
* 若 [coroutineContext] 含有 [Job], 则 [AutoSaveSetting] 会通过 [Job.invokeOnCompletion] 在 Job 完结时触发自动保存.
|
* 若 [coroutineContext] 含有 [Job], 则 [AutoSaveSetting] 会通过 [Job.invokeOnCompletion] 在 Job 完结时触发自动保存.
|
||||||
|
*
|
||||||
|
* @see LongRange Java 用户使用 [LongRange] 的构造器创建
|
||||||
|
* @see Long.rangeTo Kotlin 用户使用 [Long.rangeTo] 创建, 如 `3000..50000`
|
||||||
*/
|
*/
|
||||||
val autoSaveIntervalMillis: LongRange
|
public val autoSaveIntervalMillis: LongRange
|
||||||
get() = 30.secondsToMillis..10.minutesToSeconds
|
get() = 30.secondsToMillis..10.minutesToSeconds
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -75,7 +83,7 @@ interface AutoSaveSettingHolder : SettingHolder, CoroutineScope {
|
|||||||
*
|
*
|
||||||
* @see getSetting
|
* @see getSetting
|
||||||
*/
|
*/
|
||||||
open class AutoSaveSetting(private val owner: AutoSaveSettingHolder, private val storage: SettingStorage) :
|
public open class AutoSaveSetting(private val owner: AutoSaveSettingHolder, private val storage: SettingStorage) :
|
||||||
AbstractSetting() {
|
AbstractSetting() {
|
||||||
@Volatile
|
@Volatile
|
||||||
internal var lastAutoSaveJob: Job? = null
|
internal var lastAutoSaveJob: Job? = null
|
||||||
@ -111,7 +119,26 @@ interface AutoSaveSettingHolder : SettingHolder, CoroutineScope {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
object MemorySettingStorage : SettingStorage {
|
// TODO: 2020/7/11 document
|
||||||
|
public interface MemorySettingStorage : SettingStorage {
|
||||||
|
public companion object INSTANCE : MemorySettingStorage by MemorySettingStorageImpl
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: 2020/7/11 document
|
||||||
|
public interface MultiFileSettingStorage : SettingStorage {
|
||||||
|
public val directory: File
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
@JvmStatic
|
||||||
|
@JvmName("create")
|
||||||
|
public operator fun invoke(directory: File): MultiFileSettingStorage = MultiFileSettingStorageImpl(directory)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// internal
|
||||||
|
|
||||||
|
internal object MemorySettingStorageImpl : SettingStorage, MemorySettingStorage {
|
||||||
private val list = mutableMapOf<Class<out Setting>, Setting>()
|
private val list = mutableMapOf<Class<out Setting>, Setting>()
|
||||||
|
|
||||||
internal class MemorySettingImpl : AbstractSetting() {
|
internal class MemorySettingImpl : AbstractSetting() {
|
||||||
@ -146,9 +173,9 @@ object MemorySettingStorage : SettingStorage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MultiFileSettingStorage(
|
internal class MultiFileSettingStorageImpl(
|
||||||
private val directory: File
|
override val directory: File
|
||||||
) : SettingStorage {
|
) : SettingStorage, MultiFileSettingStorage {
|
||||||
override fun <T : Setting> load(holder: SettingHolder, settingClass: Class<T>): T = with(settingClass.kotlin) {
|
override fun <T : Setting> load(holder: SettingHolder, settingClass: Class<T>): T = with(settingClass.kotlin) {
|
||||||
val file = settingFile(holder, settingClass::class)
|
val file = settingFile(holder, settingClass::class)
|
||||||
|
|
||||||
@ -161,7 +188,7 @@ class MultiFileSettingStorage(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
if (holder is AutoSaveSettingHolder) {
|
if (holder is AutoSaveSettingHolder) {
|
||||||
AutoSaveSetting(holder, this@MultiFileSettingStorage) as T?
|
AutoSaveSetting(holder, this@MultiFileSettingStorageImpl) as T?
|
||||||
} else null
|
} else null
|
||||||
} ?: throw IllegalArgumentException(
|
} ?: throw IllegalArgumentException(
|
||||||
"Cannot create Setting instance. Make sure 'holder' is a AutoSaveSettingHolder, " +
|
"Cannot create Setting instance. Make sure 'holder' is a AutoSaveSettingHolder, " +
|
||||||
@ -189,7 +216,7 @@ class MultiFileSettingStorage(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
override fun store(holder: SettingHolder, setting: Setting) = with(setting::class) {
|
override fun store(holder: SettingHolder, setting: Setting): Unit = with(setting::class) {
|
||||||
val file = settingFile(holder, this)
|
val file = settingFile(holder, this)
|
||||||
|
|
||||||
if (file.exists() && file.isFile && file.canRead()) {
|
if (file.exists() && file.isFile && file.canRead()) {
|
||||||
|
@ -29,14 +29,14 @@ import kotlin.reflect.KProperty
|
|||||||
* @see PrimitiveValue
|
* @see PrimitiveValue
|
||||||
* @see CompositeValue
|
* @see CompositeValue
|
||||||
*/
|
*/
|
||||||
interface Value<T> {
|
public interface Value<T> {
|
||||||
var value: T
|
public var value: T
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Typically returned by [Setting.value] functions.
|
* Typically returned by [Setting.value] functions.
|
||||||
*/
|
*/
|
||||||
class SerializableValue<T>(
|
public class SerializableValue<T>(
|
||||||
private val delegate: Value<T>,
|
private val delegate: Value<T>,
|
||||||
/**
|
/**
|
||||||
* The serializer used to update and dump [delegate]
|
* The serializer used to update and dump [delegate]
|
||||||
@ -46,7 +46,7 @@ class SerializableValue<T>(
|
|||||||
override fun toString(): String = delegate.toString()
|
override fun toString(): String = delegate.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> Value<T>.serializableValueWith(
|
public fun <T> Value<T>.serializableValueWith(
|
||||||
serializer: KSerializer<T>
|
serializer: KSerializer<T>
|
||||||
): SerializableValue<T> {
|
): SerializableValue<T> {
|
||||||
return SerializableValue(
|
return SerializableValue(
|
||||||
@ -58,27 +58,30 @@ fun <T> Value<T>.serializableValueWith(
|
|||||||
/**
|
/**
|
||||||
* @see SerializableValue
|
* @see SerializableValue
|
||||||
*/
|
*/
|
||||||
interface SerializerAwareValue<T> : Value<T> {
|
public interface SerializerAwareValue<T> : Value<T> {
|
||||||
val serializer: KSerializer<Unit>
|
public val serializer: KSerializer<Unit>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> SerializerAwareValue<T>.serialize(format: StringFormat): String {
|
public fun <T> SerializerAwareValue<T>.serialize(format: StringFormat): String {
|
||||||
return format.stringify(this.serializer, Unit)
|
return format.stringify(this.serializer, Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> SerializerAwareValue<T>.serialize(format: BinaryFormat): ByteArray {
|
public fun <T> SerializerAwareValue<T>.serialize(format: BinaryFormat): ByteArray {
|
||||||
return format.dump(this.serializer, Unit)
|
return format.dump(this.serializer, Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator fun <T> Value<T>.getValue(mySetting: Any?, property: KProperty<*>): T = value
|
@JvmSynthetic
|
||||||
inline operator fun <T> Value<T>.setValue(mySetting: Any?, property: KProperty<*>, value: T) {
|
public inline operator fun <T> Value<T>.getValue(mySetting: Any?, property: KProperty<*>): T = value
|
||||||
|
|
||||||
|
@JvmSynthetic
|
||||||
|
public inline operator fun <T> Value<T>.setValue(mySetting: Any?, property: KProperty<*>, value: T) {
|
||||||
this.value = value
|
this.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The serializer for a specific kind of [Value].
|
* The serializer for a specific kind of [Value].
|
||||||
*/
|
*/
|
||||||
typealias ValueSerializer<T> = KSerializer<Value<T>>
|
public typealias ValueSerializer<T> = KSerializer<Value<T>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a observable *primitive* value wrapping.
|
* Represents a observable *primitive* value wrapping.
|
||||||
@ -92,7 +95,7 @@ typealias ValueSerializer<T> = KSerializer<Value<T>>
|
|||||||
* Note: The values are actually *boxed* because of the generic type T.
|
* Note: The values are actually *boxed* because of the generic type T.
|
||||||
* *Primitive* indicates only it is one of the 9 types mentioned above.
|
* *Primitive* indicates only it is one of the 9 types mentioned above.
|
||||||
*/
|
*/
|
||||||
interface PrimitiveValue<T> : Value<T>
|
public interface PrimitiveValue<T> : Value<T>
|
||||||
|
|
||||||
|
|
||||||
//// region PrimitiveValues CODEGEN ////
|
//// region PrimitiveValues CODEGEN ////
|
||||||
@ -100,77 +103,77 @@ interface PrimitiveValue<T> : Value<T>
|
|||||||
/**
|
/**
|
||||||
* Represents a non-null [Byte] value.
|
* Represents a non-null [Byte] value.
|
||||||
*/
|
*/
|
||||||
interface ByteValue : PrimitiveValue<Byte>
|
public interface ByteValue : PrimitiveValue<Byte>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [Short] value.
|
* Represents a non-null [Short] value.
|
||||||
*/
|
*/
|
||||||
interface ShortValue : PrimitiveValue<Short>
|
public interface ShortValue : PrimitiveValue<Short>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [Int] value.
|
* Represents a non-null [Int] value.
|
||||||
*/
|
*/
|
||||||
interface IntValue : PrimitiveValue<Int>
|
public interface IntValue : PrimitiveValue<Int>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [Long] value.
|
* Represents a non-null [Long] value.
|
||||||
*/
|
*/
|
||||||
interface LongValue : PrimitiveValue<Long>
|
public interface LongValue : PrimitiveValue<Long>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [Float] value.
|
* Represents a non-null [Float] value.
|
||||||
*/
|
*/
|
||||||
interface FloatValue : PrimitiveValue<Float>
|
public interface FloatValue : PrimitiveValue<Float>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [Double] value.
|
* Represents a non-null [Double] value.
|
||||||
*/
|
*/
|
||||||
interface DoubleValue : PrimitiveValue<Double>
|
public interface DoubleValue : PrimitiveValue<Double>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [Char] value.
|
* Represents a non-null [Char] value.
|
||||||
*/
|
*/
|
||||||
interface CharValue : PrimitiveValue<Char>
|
public interface CharValue : PrimitiveValue<Char>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [Boolean] value.
|
* Represents a non-null [Boolean] value.
|
||||||
*/
|
*/
|
||||||
interface BooleanValue : PrimitiveValue<Boolean>
|
public interface BooleanValue : PrimitiveValue<Boolean>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a non-null [String] value.
|
* Represents a non-null [String] value.
|
||||||
*/
|
*/
|
||||||
interface StringValue : PrimitiveValue<String>
|
public interface StringValue : PrimitiveValue<String>
|
||||||
|
|
||||||
//// endregion PrimitiveValues CODEGEN ////
|
//// endregion PrimitiveValues CODEGEN ////
|
||||||
|
|
||||||
|
|
||||||
@ConsoleExperimentalAPI
|
@ConsoleExperimentalAPI
|
||||||
interface CompositeValue<T> : Value<T>
|
public interface CompositeValue<T> : Value<T>
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Superclass of [CompositeListValue], [PrimitiveListValue].
|
* Superclass of [CompositeListValue], [PrimitiveListValue].
|
||||||
*/
|
*/
|
||||||
interface ListValue<E> : CompositeValue<List<E>>
|
public interface ListValue<E> : CompositeValue<List<E>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Elements can by anything, wrapped as [Value].
|
* Elements can by anything, wrapped as [Value].
|
||||||
* @param E is not primitive types.
|
* @param E is not primitive types.
|
||||||
*/
|
*/
|
||||||
interface CompositeListValue<E> : ListValue<E>
|
public interface CompositeListValue<E> : ListValue<E>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Elements can only be primitives, not wrapped.
|
* Elements can only be primitives, not wrapped.
|
||||||
* @param E is not primitive types.
|
* @param E is not primitive types.
|
||||||
*/
|
*/
|
||||||
interface PrimitiveListValue<E> : ListValue<E>
|
public interface PrimitiveListValue<E> : ListValue<E>
|
||||||
|
|
||||||
|
|
||||||
//// region PrimitiveListValue CODEGEN ////
|
//// region PrimitiveListValue CODEGEN ////
|
||||||
|
|
||||||
interface PrimitiveIntListValue : PrimitiveListValue<Int>
|
public interface PrimitiveIntListValue : PrimitiveListValue<Int>
|
||||||
interface PrimitiveLongListValue : PrimitiveListValue<Long>
|
public interface PrimitiveLongListValue : PrimitiveListValue<Long>
|
||||||
// TODO + codegen
|
// TODO + codegen
|
||||||
|
|
||||||
//// endregion PrimitiveListValue CODEGEN ////
|
//// endregion PrimitiveListValue CODEGEN ////
|
||||||
@ -179,25 +182,25 @@ interface PrimitiveLongListValue : PrimitiveListValue<Long>
|
|||||||
/**
|
/**
|
||||||
* Superclass of [CompositeSetValue], [PrimitiveSetValue].
|
* Superclass of [CompositeSetValue], [PrimitiveSetValue].
|
||||||
*/
|
*/
|
||||||
interface SetValue<E> : CompositeValue<Set<E>>
|
public interface SetValue<E> : CompositeValue<Set<E>>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Elements can by anything, wrapped as [Value].
|
* Elements can by anything, wrapped as [Value].
|
||||||
* @param E is not primitive types.
|
* @param E is not primitive types.
|
||||||
*/
|
*/
|
||||||
interface CompositeSetValue<E> : SetValue<E>
|
public interface CompositeSetValue<E> : SetValue<E>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Elements can only be primitives, not wrapped.
|
* Elements can only be primitives, not wrapped.
|
||||||
* @param E is not primitive types.
|
* @param E is not primitive types.
|
||||||
*/
|
*/
|
||||||
interface PrimitiveSetValue<E> : SetValue<E>
|
public interface PrimitiveSetValue<E> : SetValue<E>
|
||||||
|
|
||||||
|
|
||||||
//// region PrimitiveSetValue CODEGEN ////
|
//// region PrimitiveSetValue CODEGEN ////
|
||||||
|
|
||||||
interface PrimitiveIntSetValue : PrimitiveSetValue<Int>
|
public interface PrimitiveIntSetValue : PrimitiveSetValue<Int>
|
||||||
interface PrimitiveLongSetValue : PrimitiveSetValue<Long>
|
public interface PrimitiveLongSetValue : PrimitiveSetValue<Long>
|
||||||
// TODO + codegen
|
// TODO + codegen
|
||||||
|
|
||||||
//// endregion PrimitiveSetValue CODEGEN ////
|
//// endregion PrimitiveSetValue CODEGEN ////
|
||||||
@ -206,17 +209,17 @@ interface PrimitiveLongSetValue : PrimitiveSetValue<Long>
|
|||||||
/**
|
/**
|
||||||
* Superclass of [CompositeMapValue], [PrimitiveMapValue].
|
* Superclass of [CompositeMapValue], [PrimitiveMapValue].
|
||||||
*/
|
*/
|
||||||
interface MapValue<K, V> : CompositeValue<Map<K, V>>
|
public interface MapValue<K, V> : CompositeValue<Map<K, V>>
|
||||||
|
|
||||||
interface CompositeMapValue<K, V> : MapValue<K, V>
|
public interface CompositeMapValue<K, V> : MapValue<K, V>
|
||||||
|
|
||||||
interface PrimitiveMapValue<K, V> : MapValue<K, V>
|
public interface PrimitiveMapValue<K, V> : MapValue<K, V>
|
||||||
|
|
||||||
|
|
||||||
//// region PrimitiveMapValue CODEGEN ////
|
//// region PrimitiveMapValue CODEGEN ////
|
||||||
|
|
||||||
interface PrimitiveIntIntMapValue : PrimitiveMapValue<Int, Int>
|
public interface PrimitiveIntIntMapValue : PrimitiveMapValue<Int, Int>
|
||||||
interface PrimitiveIntLongMapValue : PrimitiveMapValue<Int, Long>
|
public interface PrimitiveIntLongMapValue : PrimitiveMapValue<Int, Long>
|
||||||
// TODO + codegen
|
// TODO + codegen
|
||||||
|
|
||||||
//// endregion PrimitiveSetValue CODEGEN ////
|
//// endregion PrimitiveSetValue CODEGEN ////
|
||||||
|
@ -98,7 +98,6 @@ internal abstract class ShortValueImpl : ShortValue, SerializerAwareValue<Short>
|
|||||||
else value.hashCode() * 31
|
else value.hashCode() * 31
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit>, AbstractValueImpl<Int> {
|
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit>, AbstractValueImpl<Int> {
|
||||||
constructor()
|
constructor()
|
||||||
constructor(default: Int) {
|
constructor(default: Int) {
|
||||||
|
@ -19,31 +19,31 @@ internal object BuiltInSerializerConstants {
|
|||||||
//// region BuiltInSerializerConstantsPrimitives CODEGEN ////
|
//// region BuiltInSerializerConstantsPrimitives CODEGEN ////
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val ByteSerializerDescriptor = Byte.serializer().descriptor
|
internal val ByteSerializerDescriptor = Byte.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val ShortSerializerDescriptor = Short.serializer().descriptor
|
internal val ShortSerializerDescriptor = Short.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val IntSerializerDescriptor = Int.serializer().descriptor
|
internal val IntSerializerDescriptor = Int.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val LongSerializerDescriptor = Long.serializer().descriptor
|
internal val LongSerializerDescriptor = Long.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val FloatSerializerDescriptor = Float.serializer().descriptor
|
internal val FloatSerializerDescriptor = Float.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val DoubleSerializerDescriptor = Double.serializer().descriptor
|
internal val DoubleSerializerDescriptor = Double.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val CharSerializerDescriptor = Char.serializer().descriptor
|
internal val CharSerializerDescriptor = Char.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val BooleanSerializerDescriptor = Boolean.serializer().descriptor
|
internal val BooleanSerializerDescriptor = Boolean.serializer().descriptor
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
val StringSerializerDescriptor = String.serializer().descriptor
|
internal val StringSerializerDescriptor = String.serializer().descriptor
|
||||||
|
|
||||||
//// endregion BuiltInSerializerConstantsPrimitives CODEGEN ////
|
//// endregion BuiltInSerializerConstantsPrimitives CODEGEN ////
|
||||||
}
|
}
|
||||||
@ -76,103 +76,86 @@ internal fun Setting.valueImpl(default: Byte): SerializerAwareValue<Byte> {
|
|||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.byteValueImpl(): SerializerAwareValue<Byte> {
|
internal fun Setting.byteValueImpl(): SerializerAwareValue<Byte> {
|
||||||
return object : ByteValueImpl() {
|
return object : ByteValueImpl() {
|
||||||
override fun onChanged() = this@byteValueImpl.onValueChanged(this)
|
override fun onChanged() = this@byteValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: Short): SerializerAwareValue<Short> {
|
internal fun Setting.valueImpl(default: Short): SerializerAwareValue<Short> {
|
||||||
return object : ShortValueImpl(default) {
|
return object : ShortValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.shortValueImpl(): SerializerAwareValue<Short> {
|
internal fun Setting.shortValueImpl(): SerializerAwareValue<Short> {
|
||||||
return object : ShortValueImpl() {
|
return object : ShortValueImpl() {
|
||||||
override fun onChanged() = this@shortValueImpl.onValueChanged(this)
|
override fun onChanged() = this@shortValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: Int): SerializerAwareValue<Int> {
|
internal fun Setting.valueImpl(default: Int): SerializerAwareValue<Int> {
|
||||||
return object : IntValueImpl(default) {
|
return object : IntValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.intValueImpl(): SerializerAwareValue<Int> {
|
internal fun Setting.intValueImpl(): SerializerAwareValue<Int> {
|
||||||
return object : IntValueImpl() {
|
return object : IntValueImpl() {
|
||||||
override fun onChanged() = this@intValueImpl.onValueChanged(this)
|
override fun onChanged() = this@intValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: Long): SerializerAwareValue<Long> {
|
internal fun Setting.valueImpl(default: Long): SerializerAwareValue<Long> {
|
||||||
return object : LongValueImpl(default) {
|
return object : LongValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.longValueImpl(): SerializerAwareValue<Long> {
|
internal fun Setting.longValueImpl(): SerializerAwareValue<Long> {
|
||||||
return object : LongValueImpl() {
|
return object : LongValueImpl() {
|
||||||
override fun onChanged() = this@longValueImpl.onValueChanged(this)
|
override fun onChanged() = this@longValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: Float): SerializerAwareValue<Float> {
|
internal fun Setting.valueImpl(default: Float): SerializerAwareValue<Float> {
|
||||||
return object : FloatValueImpl(default) {
|
return object : FloatValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.floatValueImpl(): SerializerAwareValue<Float> {
|
internal fun Setting.floatValueImpl(): SerializerAwareValue<Float> {
|
||||||
return object : FloatValueImpl() {
|
return object : FloatValueImpl() {
|
||||||
override fun onChanged() = this@floatValueImpl.onValueChanged(this)
|
override fun onChanged() = this@floatValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: Double): SerializerAwareValue<Double> {
|
internal fun Setting.valueImpl(default: Double): SerializerAwareValue<Double> {
|
||||||
return object : DoubleValueImpl(default) {
|
return object : DoubleValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.doubleValueImpl(): SerializerAwareValue<Double> {
|
internal fun Setting.doubleValueImpl(): SerializerAwareValue<Double> {
|
||||||
return object : DoubleValueImpl() {
|
return object : DoubleValueImpl() {
|
||||||
override fun onChanged() = this@doubleValueImpl.onValueChanged(this)
|
override fun onChanged() = this@doubleValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: Char): SerializerAwareValue<Char> {
|
internal fun Setting.valueImpl(default: Char): SerializerAwareValue<Char> {
|
||||||
return object : CharValueImpl(default) {
|
return object : CharValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.charValueImpl(): SerializerAwareValue<Char> {
|
internal fun Setting.charValueImpl(): SerializerAwareValue<Char> {
|
||||||
return object : CharValueImpl() {
|
return object : CharValueImpl() {
|
||||||
override fun onChanged() = this@charValueImpl.onValueChanged(this)
|
override fun onChanged() = this@charValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: Boolean): SerializerAwareValue<Boolean> {
|
internal fun Setting.valueImpl(default: Boolean): SerializerAwareValue<Boolean> {
|
||||||
return object : BooleanValueImpl(default) {
|
return object : BooleanValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.booleanValueImpl(): SerializerAwareValue<Boolean> {
|
internal fun Setting.booleanValueImpl(): SerializerAwareValue<Boolean> {
|
||||||
return object : BooleanValueImpl() {
|
return object : BooleanValueImpl() {
|
||||||
override fun onChanged() = this@booleanValueImpl.onValueChanged(this)
|
override fun onChanged() = this@booleanValueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.valueImpl(default: String): SerializerAwareValue<String> {
|
internal fun Setting.valueImpl(default: String): SerializerAwareValue<String> {
|
||||||
return object : StringValueImpl(default) {
|
return object : StringValueImpl(default) {
|
||||||
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
override fun onChanged() = this@valueImpl.onValueChanged(this)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun Setting.stringValueImpl(): SerializerAwareValue<String> {
|
internal fun Setting.stringValueImpl(): SerializerAwareValue<String> {
|
||||||
return object : StringValueImpl() {
|
return object : StringValueImpl() {
|
||||||
override fun onChanged() = this@stringValueImpl.onValueChanged(this)
|
override fun onChanged() = this@stringValueImpl.onValueChanged(this)
|
||||||
|
@ -17,7 +17,7 @@ import net.mamoe.mirai.contact.User
|
|||||||
/**
|
/**
|
||||||
* 判断此用户是否为 console 管理员
|
* 判断此用户是否为 console 管理员
|
||||||
*/
|
*/
|
||||||
val User.isManager: Boolean
|
public val User.isManager: Boolean
|
||||||
get() = this.bot.managers.contains(this.id)
|
get() = this.bot.managers.contains(this.id)
|
||||||
|
|
||||||
internal fun Bot.addManager(long: Long): Boolean {
|
internal fun Bot.addManager(long: Long): Boolean {
|
||||||
@ -25,9 +25,9 @@ internal fun Bot.addManager(long: Long): Boolean {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Bot.removeManager(long: Long) {
|
public fun Bot.removeManager(long: Long) {
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
val Bot.managers: List<Long>
|
public val Bot.managers: List<Long>
|
||||||
get() = TODO()
|
get() = TODO()
|
||||||
|
@ -7,47 +7,45 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("INAPPLICABLE_JVM_NAME", "unused")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.utils
|
package net.mamoe.mirai.console.utils
|
||||||
|
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.runBlocking
|
||||||
|
import kotlinx.coroutines.sync.Mutex
|
||||||
|
import kotlinx.coroutines.sync.withLock
|
||||||
import net.mamoe.mirai.console.MiraiConsole
|
import net.mamoe.mirai.console.MiraiConsole
|
||||||
import java.util.concurrent.Executors
|
|
||||||
|
|
||||||
@Suppress("unused")
|
/**
|
||||||
object ConsoleInput {
|
* Console 输入. 由于 console 接管了 stdin, [readLine] 等操作需要在这里进行.
|
||||||
private val inputDispatcher = Executors.newFixedThreadPool(1).asCoroutineDispatcher()
|
*/
|
||||||
|
public interface ConsoleInput {
|
||||||
|
/**
|
||||||
|
* 以 [提示][hint] 向用户索要一个输入
|
||||||
|
*/
|
||||||
|
@JvmSynthetic
|
||||||
|
public suspend fun requestInput(hint: String): String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 向用户索要一个Input
|
* 以 [提示][hint] 向用户索要一个输入. 仅供 Java 调用者使用
|
||||||
* 你需要提供一个hint(提示)并等待获取一个结果
|
|
||||||
* 具体索要方式将根据frontend不同而不同
|
|
||||||
* 如弹出框,或一行字
|
|
||||||
*/
|
*/
|
||||||
suspend fun requestInput(
|
@JvmName("requestInput")
|
||||||
hint: String
|
@JavaFriendlyAPI
|
||||||
): String {
|
public fun requestInputBlocking(hint: String): String
|
||||||
return withContext(inputDispatcher) {
|
|
||||||
MiraiConsole.frontEnd.requestInput(hint)
|
public companion object INSTANCE : ConsoleInput by ConsoleInputImpl {
|
||||||
}
|
public suspend inline fun MiraiConsole.requestInput(hint: String): String = ConsoleInput.requestInput(hint)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestInputBlocking(hint: String): String = runBlocking { requestInput(hint) }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* asnyc获取
|
|
||||||
*/
|
|
||||||
fun requestInputAsync(
|
|
||||||
scope: CoroutineScope,
|
|
||||||
hint: String
|
|
||||||
): Deferred<String> {
|
|
||||||
return scope.async {
|
|
||||||
requestInput(hint)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
suspend fun MiraiConsole.requestInput(hint: String): String = requestInput(hint)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Suppress("unused")
|
||||||
|
internal object ConsoleInputImpl : ConsoleInput {
|
||||||
|
private val inputLock = Mutex()
|
||||||
|
|
||||||
|
override suspend fun requestInput(
|
||||||
|
hint: String
|
||||||
|
): String = inputLock.withLock { MiraiConsole.frontEnd.requestInput(hint) }
|
||||||
|
|
||||||
|
@JavaFriendlyAPI
|
||||||
|
override fun requestInputBlocking(hint: String): String = runBlocking { requestInput(hint) }
|
||||||
|
}
|
@ -19,7 +19,7 @@ internal annotation class JavaFriendlyAPI
|
|||||||
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
|
@RequiresOptIn(level = RequiresOptIn.Level.ERROR)
|
||||||
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR, CLASS, FUNCTION, PROPERTY)
|
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR, CLASS, FUNCTION, PROPERTY)
|
||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
annotation class ConsoleInternalAPI(
|
public annotation class ConsoleInternalAPI(
|
||||||
val message: String = ""
|
val message: String = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -33,6 +33,6 @@ annotation class ConsoleInternalAPI(
|
|||||||
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||||
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR)
|
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR)
|
||||||
@MustBeDocumented
|
@MustBeDocumented
|
||||||
annotation class ConsoleExperimentalAPI(
|
public annotation class ConsoleExperimentalAPI(
|
||||||
val message: String = ""
|
val message: String = ""
|
||||||
)
|
)
|
||||||
|
@ -25,8 +25,8 @@ import kotlin.coroutines.CoroutineContext
|
|||||||
*
|
*
|
||||||
* @see JavaPlugin.scheduler 获取实例
|
* @see JavaPlugin.scheduler 获取实例
|
||||||
*/
|
*/
|
||||||
class JavaPluginScheduler internal constructor(parentCoroutineContext: CoroutineContext) : CoroutineScope {
|
public class JavaPluginScheduler internal constructor(parentCoroutineContext: CoroutineContext) : CoroutineScope {
|
||||||
override val coroutineContext: CoroutineContext =
|
public override val coroutineContext: CoroutineContext =
|
||||||
parentCoroutineContext + SupervisorJob(parentCoroutineContext[Job])
|
parentCoroutineContext + SupervisorJob(parentCoroutineContext[Job])
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -36,7 +36,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine
|
|||||||
*
|
*
|
||||||
* @see Future.cancel 取消这个任务
|
* @see Future.cancel 取消这个任务
|
||||||
*/
|
*/
|
||||||
fun repeating(intervalMs: Long, runnable: Runnable): Future<Void?> {
|
public fun repeating(intervalMs: Long, runnable: Runnable): Future<Void?> {
|
||||||
return this.future {
|
return this.future {
|
||||||
while (isActive) {
|
while (isActive) {
|
||||||
withContext(Dispatchers.IO) { runnable.run() }
|
withContext(Dispatchers.IO) { runnable.run() }
|
||||||
@ -51,7 +51,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine
|
|||||||
*
|
*
|
||||||
* 在延迟 [delayMillis] 后执行 [runnable]
|
* 在延迟 [delayMillis] 后执行 [runnable]
|
||||||
*/
|
*/
|
||||||
fun delayed(delayMillis: Long, runnable: Runnable): CompletableFuture<Void?> {
|
public fun delayed(delayMillis: Long, runnable: Runnable): CompletableFuture<Void?> {
|
||||||
return future {
|
return future {
|
||||||
delay(delayMillis)
|
delay(delayMillis)
|
||||||
withContext(Dispatchers.IO) {
|
withContext(Dispatchers.IO) {
|
||||||
@ -66,7 +66,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine
|
|||||||
*
|
*
|
||||||
* 在延迟 [delayMillis] 后执行 [runnable]
|
* 在延迟 [delayMillis] 后执行 [runnable]
|
||||||
*/
|
*/
|
||||||
fun <R> delayed(delayMillis: Long, runnable: Callable<R>): CompletableFuture<Void?> {
|
public fun <R> delayed(delayMillis: Long, runnable: Callable<R>): CompletableFuture<Void?> {
|
||||||
return future {
|
return future {
|
||||||
delay(delayMillis)
|
delay(delayMillis)
|
||||||
withContext(Dispatchers.IO) { runnable.call() }
|
withContext(Dispatchers.IO) { runnable.call() }
|
||||||
@ -77,7 +77,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine
|
|||||||
/**
|
/**
|
||||||
* 异步执行一个任务, 最终返回 [Future], 与 Java 使用方法无异, 但效率更高且可以在插件关闭时停止
|
* 异步执行一个任务, 最终返回 [Future], 与 Java 使用方法无异, 但效率更高且可以在插件关闭时停止
|
||||||
*/
|
*/
|
||||||
fun <R> async(supplier: Callable<R>): Future<R> {
|
public fun <R> async(supplier: Callable<R>): Future<R> {
|
||||||
return future {
|
return future {
|
||||||
withContext(Dispatchers.IO) { supplier.call() }
|
withContext(Dispatchers.IO) { supplier.call() }
|
||||||
}
|
}
|
||||||
@ -86,7 +86,7 @@ class JavaPluginScheduler internal constructor(parentCoroutineContext: Coroutine
|
|||||||
/**
|
/**
|
||||||
* 异步执行一个任务, 没有返回
|
* 异步执行一个任务, 没有返回
|
||||||
*/
|
*/
|
||||||
fun async(runnable: Runnable): Future<Void?> {
|
public fun async(runnable: Runnable): Future<Void?> {
|
||||||
return future {
|
return future {
|
||||||
withContext(Dispatchers.IO) { runnable.run() }
|
withContext(Dispatchers.IO) { runnable.run() }
|
||||||
null
|
null
|
||||||
|
@ -10,26 +10,26 @@ import kotlin.reflect.KClass
|
|||||||
/**
|
/**
|
||||||
* 资源容器.
|
* 资源容器.
|
||||||
*/
|
*/
|
||||||
interface ResourceContainer {
|
public interface ResourceContainer {
|
||||||
/**
|
/**
|
||||||
* 获取一个资源文件
|
* 获取一个资源文件
|
||||||
*/
|
*/
|
||||||
fun getResourceAsStream(name: String): InputStream
|
public fun getResourceAsStream(name: String): InputStream
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取一个资源文件并以 [Charsets.UTF_8] 编码为 [String]
|
* 读取一个资源文件并以 [Charsets.UTF_8] 编码为 [String]
|
||||||
*/
|
*/
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
fun getResource(name: String): String = getResource(name, Charsets.UTF_8)
|
public fun getResource(name: String): String = getResource(name, Charsets.UTF_8)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 读取一个资源文件并以 [charset] 编码为 [String]
|
* 读取一个资源文件并以 [charset] 编码为 [String]
|
||||||
*/
|
*/
|
||||||
@JvmDefault
|
@JvmDefault
|
||||||
fun getResource(name: String, charset: Charset): String =
|
public fun getResource(name: String, charset: Charset): String =
|
||||||
this.getResourceAsStream(name).use { it.readBytes() }.encodeToString()
|
this.getResourceAsStream(name).use { it.readBytes() }.encodeToString()
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
/**
|
/**
|
||||||
* 使用 [Class.getResourceAsStream] 读取资源文件
|
* 使用 [Class.getResourceAsStream] 读取资源文件
|
||||||
*
|
*
|
||||||
@ -37,22 +37,23 @@ interface ResourceContainer {
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@JavaFriendlyAPI
|
@JavaFriendlyAPI
|
||||||
fun byClass(clazz: Class<*>): ResourceContainer = clazz.asResourceContainer()
|
public fun byClass(clazz: Class<*>): ResourceContainer = clazz.asResourceContainer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 [Class.getResourceAsStream] 读取资源文件
|
||||||
|
*/
|
||||||
|
public fun KClass<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this.java)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用 [Class.getResourceAsStream] 读取资源文件
|
||||||
|
*/
|
||||||
|
public fun Class<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this)
|
||||||
|
|
||||||
|
|
||||||
internal class ClassAsResourceContainer(
|
internal class ClassAsResourceContainer(
|
||||||
private val clazz: Class<*>
|
private val clazz: Class<*>
|
||||||
) : ResourceContainer {
|
) : ResourceContainer {
|
||||||
override fun getResourceAsStream(name: String): InputStream = clazz.getResourceAsStream(name)
|
override fun getResourceAsStream(name: String): InputStream = clazz.getResourceAsStream(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 [Class.getResourceAsStream] 读取资源文件
|
|
||||||
*/
|
|
||||||
fun KClass<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this.java)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 使用 [Class.getResourceAsStream] 读取资源文件
|
|
||||||
*/
|
|
||||||
fun Class<*>.asResourceContainer(): ResourceContainer = ClassAsResourceContainer(this)
|
|
@ -14,34 +14,25 @@ package net.mamoe.mirai.console.utils
|
|||||||
import org.jetbrains.annotations.Range
|
import org.jetbrains.annotations.Range
|
||||||
import kotlin.contracts.InvocationKind
|
import kotlin.contracts.InvocationKind
|
||||||
import kotlin.contracts.contract
|
import kotlin.contracts.contract
|
||||||
|
import kotlin.internal.InlineOnly
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 执行 [n] 次 [block], 在第一次成功时返回执行结果, 在捕获到异常时返回异常.
|
* 执行 [n] 次 [block], 在第一次成功时返回执行结果, 在捕获到异常时返回异常.
|
||||||
*/
|
*/
|
||||||
@kotlin.internal.InlineOnly
|
@InlineOnly
|
||||||
inline fun <R> retryCatching(n: @Range(from = 1, to = Long.MAX_VALUE) Int, block: () -> R): Result<R> {
|
public inline fun <R> retryCatching(n: @Range(from = 1, to = Int.MAX_VALUE.toLong()) Int, block: () -> R): Result<R> {
|
||||||
contract {
|
contract {
|
||||||
callsInPlace(block, InvocationKind.AT_LEAST_ONCE)
|
callsInPlace(block, InvocationKind.AT_LEAST_ONCE)
|
||||||
}
|
}
|
||||||
require(n >= 0) { "param n for retryCatching must not be negative" }
|
require(n >= 1) { "param n for retryCatching must not be negative" }
|
||||||
var exception: Throwable? = null
|
var exception: Throwable? = null
|
||||||
repeat(n) {
|
repeat(n) {
|
||||||
try {
|
try {
|
||||||
return Result.success(block())
|
return Result.success(block())
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
exception?.addSuppressedMirai(e)
|
exception?.addSuppressed(e)
|
||||||
exception = e
|
exception = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Result.failure(exception!!)
|
return Result.failure(exception!!)
|
||||||
}
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal fun Throwable.addSuppressedMirai(e: Throwable) {
|
|
||||||
if (e === this) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
kotlin.runCatching {
|
|
||||||
this.addSuppressed(e)
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -14,7 +14,7 @@ object Versions {
|
|||||||
const val consoleTerminal = "0.1.0"
|
const val consoleTerminal = "0.1.0"
|
||||||
const val consolePure = "0.1-dev-1"
|
const val consolePure = "0.1-dev-1"
|
||||||
|
|
||||||
const val kotlin = "1.3.72"
|
const val kotlin = "1.4-M3"
|
||||||
const val coroutines = "1.3.7"
|
const val coroutines = "1.3.7"
|
||||||
const val serialization = "0.20.0"
|
const val serialization = "0.20.0"
|
||||||
const val ktor = "1.3.2"
|
const val ktor = "1.3.2"
|
||||||
|
Loading…
Reference in New Issue
Block a user