Separate Command.names into Command.primaryName and Command.secondaryNames such that primaryName is compulsory while secondaryNames are optional.

This commit is contained in:
Him188 2020-09-18 22:55:19 +08:00
parent 899c6266dd
commit 7762ea2f65
22 changed files with 110 additions and 68 deletions

View File

@ -16,8 +16,8 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register
import net.mamoe.mirai.console.command.java.JCommand import net.mamoe.mirai.console.command.java.JCommand
import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission
import net.mamoe.mirai.console.internal.command.isValidSubName
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionId
import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.MessageChain
/** /**
@ -33,13 +33,17 @@ import net.mamoe.mirai.message.data.MessageChain
*/ */
public interface Command { public interface Command {
/** /**
* 指令名. 需要至少有一个元素. 所有元素都不能带有空格 * 主指令名. 将会参与构成 [Permission.id].
*
* 第一个元素会作为主指令名.
* *
* 不允许包含 [空格][Char.isWhitespace], '.', ':'.
*/
public val primaryName: String
/**
* 次要指令名
* @see Command.primaryName 获取主指令名 * @see Command.primaryName 获取主指令名
*/ */
public val names: Array<out String> public val secondaryNames: Array<out String>
/** /**
* 用法说明, 用于发送给用户. [usage] 一般包含 [description]. * 用法说明, 用于发送给用户. [usage] 一般包含 [description].
@ -52,14 +56,18 @@ public interface Command {
public val description: String public val description: String
/** /**
* 指令权限 * 此指令所分配的权限.
*
* ### 实现约束
* - [Permission.id] 应由 [CommandOwner.permissionId] 创建. 因此保证相同的 [PermissionId.namespace]
* - [PermissionId.name] 应为 [主指令名][primaryName]
*/ */
public val permission: Permission public val permission: Permission
/** /**
* `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选. * `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选.
* *
* 会影响消息语境中的解析. * 会影响聊天语境中的解析.
*/ */
public val prefixOptional: Boolean public val prefixOptional: Boolean
@ -80,17 +88,34 @@ public interface Command {
public suspend fun CommandSender.onCommand(args: MessageChain) public suspend fun CommandSender.onCommand(args: MessageChain)
public companion object { public companion object {
/** /**
* 主要指令名. [Command.names] 的第一个元素. * 获取所有指令名称 (包含 [primaryName] [secondaryNames]).
*
* @return 数组大小至少为 1. 第一个元素总是 [primaryName]. 随后是保持原顺序的 [secondaryNames]
*/ */
@JvmStatic @JvmStatic
public val Command.primaryName: String public val Command.allNames: Array<String>
get() = names[0] get() = arrayOf(primaryName, *secondaryNames)
/**
* 检查指令名的合法性. 在非法时抛出 [IllegalArgumentException]
*/
@Throws(IllegalArgumentException::class)
public fun checkCommandName(name: String) {
when {
name.isBlank() -> throw IllegalArgumentException("Command name should not be blank.")
name.any { it.isWhitespace() } -> throw IllegalArgumentException("Spaces is not yet allowed in command name.")
name.contains(':') -> throw IllegalArgumentException("':' is forbidden in command name.")
name.contains('.') -> throw IllegalArgumentException("'.' is forbidden in command name.")
}
}
} }
} }
/** /**
* 调用 [Command.onCommand] * 调用 [Command.onCommand]
* @see Command.onCommand
*/ */
@JvmSynthetic @JvmSynthetic
public suspend inline fun Command.onCommand(sender: CommandSender, args: MessageChain): Unit = public suspend inline fun Command.onCommand(sender: CommandSender, args: MessageChain): Unit =
@ -105,19 +130,14 @@ public suspend inline fun Command.onCommand(sender: CommandSender, args: Message
*/ */
public abstract class AbstractCommand public abstract class AbstractCommand
@JvmOverloads constructor( @JvmOverloads constructor(
/** 指令拥有者. */ public final override val owner: CommandOwner,
public override val owner: CommandOwner, public final override val primaryName: String,
vararg names: String, public final override val secondaryNames: Array<out String>,
description: String = "<no description available>", public override val description: String = "<no description available>",
parentPermission: Permission = owner.parentPermission, parentPermission: Permission = owner.parentPermission,
/** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */
public override val prefixOptional: Boolean = false, public override val prefixOptional: Boolean = false,
) : Command { ) : Command {
public override val description: String = description.trimIndent() public override val usage: String get() = description
public final override val names: Array<out String> =
names.map(String::trim).filterNot(String::isEmpty).map(String::toLowerCase).also { list ->
list.firstOrNull { !it.isValidSubName() }?.let { error("Invalid name: $it") }
}.toTypedArray()
public override val permission: Permission by lazy { createOrFindCommandPermission(parentPermission) } public override val permission: Permission by lazy { createOrFindCommandPermission(parentPermission) }
} }

View File

@ -11,7 +11,6 @@
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
/** /**

View File

@ -53,8 +53,8 @@ public interface CommandManager {
* *
* @param override 是否覆盖重名指令. * @param override 是否覆盖重名指令.
* *
* 若原有指令 P, [Command.names] 'a', 'b', 'c'. * 若原有指令 P, [Command.secondaryNames] 'a', 'b', 'c'.
* 新指令 Q, [Command.names] 'b', 将会覆盖原指令 A 注册的 'b'. * 新指令 Q, [Command.secondaryNames] 'b', 将会覆盖原指令 A 注册的 'b'.
* *
* 即注册完成后, 'a' 'c' 将会解析到指令 P, 'b' 会解析到指令 Q. * 即注册完成后, 'a' 'c' 将会解析到指令 P, 'b' 会解析到指令 Q.
* *

View File

@ -36,5 +36,5 @@ public interface CommandOwner : PermissionIdNamespace {
internal object ConsoleCommandOwner : CommandOwner { internal object ConsoleCommandOwner : CommandOwner {
override val parentPermission: Permission get() = BuiltInCommands.parentPermission override val parentPermission: Permission get() = BuiltInCommands.parentPermission
override fun permissionId(name: String): PermissionId = PermissionId("console", "command.$name") override fun permissionId(name: String): PermissionId = PermissionId("console", name)
} }

View File

@ -9,7 +9,6 @@
package net.mamoe.mirai.console.command package net.mamoe.mirai.console.command
import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand
/** /**

View File

@ -81,12 +81,13 @@ import kotlin.annotation.AnnotationTarget.FUNCTION
*/ */
public abstract class CompositeCommand( public abstract class CompositeCommand(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, primaryName: String,
vararg secondaryNames: String,
description: String = "no description available", description: String = "no description available",
parentPermission: Permission = owner.parentPermission, parentPermission: Permission = owner.parentPermission,
prefixOptional: Boolean = false, prefixOptional: Boolean = false,
overrideContext: CommandArgumentContext = EmptyCommandArgumentContext, overrideContext: CommandArgumentContext = EmptyCommandArgumentContext,
) : Command, AbstractReflectionCommand(owner, names, description, parentPermission, prefixOptional), ) : Command, AbstractReflectionCommand(owner, primaryName, secondaryNames = secondaryNames, description, parentPermission, prefixOptional),
CommandArgumentContextAware { CommandArgumentContextAware {
/** /**

View File

@ -35,8 +35,10 @@ public abstract class RawCommand(
* @see CommandOwner * @see CommandOwner
*/ */
public override val owner: CommandOwner, public override val owner: CommandOwner,
/** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */ /** 主指令名. */
public override vararg val names: String, public override val primaryName: String,
/** 次要指令名. */
public override vararg val secondaryNames: String,
/** 用法说明, 用于发送给用户 */ /** 用法说明, 用于发送给用户 */
public override val usage: String = "<no usages given>", public override val usage: String = "<no usages given>",
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */ /** 指令描述, 用于显示在 [BuiltInCommands.Help] */

View File

@ -50,12 +50,13 @@ import net.mamoe.mirai.message.data.MessageChain
*/ */
public abstract class SimpleCommand( public abstract class SimpleCommand(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, primaryName: String,
vararg secondaryNames: String,
description: String = "no description available", description: String = "no description available",
parentPermission: Permission = owner.parentPermission, parentPermission: Permission = owner.parentPermission,
prefixOptional: Boolean = false, prefixOptional: Boolean = false,
overrideContext: CommandArgumentContext = EmptyCommandArgumentContext, overrideContext: CommandArgumentContext = EmptyCommandArgumentContext,
) : Command, AbstractReflectionCommand(owner, names, description, parentPermission, prefixOptional), ) : Command, AbstractReflectionCommand(owner, primaryName, secondaryNames = secondaryNames, description, parentPermission, prefixOptional),
CommandArgumentContextAware { CommandArgumentContextAware {
/** /**

View File

@ -69,11 +69,12 @@ import net.mamoe.mirai.console.permission.Permission
public abstract class JCompositeCommand public abstract class JCompositeCommand
@JvmOverloads constructor( @JvmOverloads constructor(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, primaryName: String,
vararg secondaryNames: String,
parentPermission: Permission = owner.parentPermission, parentPermission: Permission = owner.parentPermission,
) : CompositeCommand(owner, *names, parentPermission = parentPermission) { ) : CompositeCommand(owner, primaryName, secondaryNames = secondaryNames, parentPermission = parentPermission) {
/** 指令描述, 用于显示在 [BuiltInCommands.Help] */ /** 指令描述, 用于显示在 [BuiltInCommands.HelpCommand] */
public final override var description: String = "<no descriptions given>" public final override var description: String = "<no descriptions available>"
protected set protected set
public final override var permission: Permission = super.permission public final override var permission: Permission = super.permission

View File

@ -52,7 +52,7 @@ public abstract class JRawCommand
*/ */
public override val owner: CommandOwner, public override val owner: CommandOwner,
/** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */ /** 指令名. 需要至少有一个元素. 所有元素都不能带有空格 */
public override vararg val names: String, public override vararg val secondaryNames: String,
parentPermission: Permission = owner.parentPermission, parentPermission: Permission = owner.parentPermission,
) : Command { ) : Command {
/** 用法说明, 用于发送给用户 */ /** 用法说明, 用于发送给用户 */

View File

@ -41,9 +41,10 @@ import net.mamoe.mirai.console.permission.Permission
*/ */
public abstract class JSimpleCommand( public abstract class JSimpleCommand(
owner: CommandOwner, owner: CommandOwner,
vararg names: String, primaryName: String,
vararg secondaryNames: String,
basePermission: Permission, basePermission: Permission,
) : SimpleCommand(owner, *names, parentPermission = basePermission) { ) : SimpleCommand(owner, primaryName, secondaryNames = secondaryNames, parentPermission = basePermission) {
public override var description: String = super.description public override var description: String = super.description
protected set protected set

View File

@ -23,7 +23,6 @@ import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.MiraiConsoleFrontEndDescription import net.mamoe.mirai.console.MiraiConsoleFrontEndDescription
import net.mamoe.mirai.console.MiraiConsoleImplementation import net.mamoe.mirai.console.MiraiConsoleImplementation
import net.mamoe.mirai.console.command.BuiltInCommands import net.mamoe.mirai.console.command.BuiltInCommands
import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.ConsoleCommandSender import net.mamoe.mirai.console.command.ConsoleCommandSender
import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.data.PluginDataStorage
@ -191,6 +190,10 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
PluginManagerImpl.enableAllLoadedPlugins() PluginManagerImpl.enableAllLoadedPlugins()
for (registeredCommand in CommandManager.allRegisteredCommands) {
registeredCommand.permission // init
}
mainLogger.info { "${PluginManagerImpl.plugins.size} plugin(s) enabled." } mainLogger.info { "${PluginManagerImpl.plugins.size} plugin(s) enabled." }
} }

View File

@ -14,7 +14,6 @@ import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.command.* import net.mamoe.mirai.console.command.*
import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.CommandSender.Companion.toCommandSender import net.mamoe.mirai.console.command.CommandSender.Companion.toCommandSender
import net.mamoe.mirai.event.Listener import net.mamoe.mirai.event.Listener
import net.mamoe.mirai.event.subscribeAlways import net.mamoe.mirai.event.subscribeAlways
@ -101,7 +100,7 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
override fun Command.register(override: Boolean): Boolean { override fun Command.register(override: Boolean): Boolean {
if (this is CompositeCommand) this.subCommands // init lazy if (this is CompositeCommand) this.subCommands // init lazy
this.permission // init lazy this.permission // init lazy
this.names // init lazy this.secondaryNames // init lazy
this.description // init lazy this.description // init lazy
this.usage // init lazy this.usage // init lazy
@ -111,13 +110,13 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
} }
registeredCommands.add(this@register) registeredCommands.add(this@register)
if (this.prefixOptional) { if (this.prefixOptional) {
for (name in this.names) { for (name in this.secondaryNames) {
val lowerCaseName = name.toLowerCase() val lowerCaseName = name.toLowerCase()
optionalPrefixCommandMap[lowerCaseName] = this optionalPrefixCommandMap[lowerCaseName] = this
requiredPrefixCommandMap[lowerCaseName] = this requiredPrefixCommandMap[lowerCaseName] = this
} }
} else { } else {
for (name in this.names) { for (name in this.secondaryNames) {
val lowerCaseName = name.toLowerCase() val lowerCaseName = name.toLowerCase()
optionalPrefixCommandMap.remove(lowerCaseName) // ensure resolution consistency optionalPrefixCommandMap.remove(lowerCaseName) // ensure resolution consistency
requiredPrefixCommandMap[lowerCaseName] = this requiredPrefixCommandMap[lowerCaseName] = this
@ -128,15 +127,15 @@ internal object CommandManagerImpl : CommandManager, CoroutineScope by Coroutine
} }
override fun Command.findDuplicate(): Command? = override fun Command.findDuplicate(): Command? =
registeredCommands.firstOrNull { it.names intersectsIgnoringCase this.names } registeredCommands.firstOrNull { it.secondaryNames intersectsIgnoringCase this.secondaryNames }
override fun Command.unregister(): Boolean = modifyLock.withLock { override fun Command.unregister(): Boolean = modifyLock.withLock {
if (this.prefixOptional) { if (this.prefixOptional) {
this.names.forEach { this.secondaryNames.forEach {
optionalPrefixCommandMap.remove(it) optionalPrefixCommandMap.remove(it)
} }
} }
this.names.forEach { this.secondaryNames.forEach {
requiredPrefixCommandMap.remove(it) requiredPrefixCommandMap.remove(it)
} }
registeredCommands.remove(this) registeredCommands.remove(this)

View File

@ -12,7 +12,6 @@
package net.mamoe.mirai.console.internal.command package net.mamoe.mirai.console.internal.command
import net.mamoe.mirai.console.command.* import net.mamoe.mirai.console.command.*
import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.description.CommandArgumentContext import net.mamoe.mirai.console.command.description.CommandArgumentContext
import net.mamoe.mirai.console.command.description.CommandArgumentContextAware import net.mamoe.mirai.console.command.description.CommandArgumentContextAware
import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip
@ -42,19 +41,21 @@ internal object SimpleCommandSubCommandAnnotationResolver :
function.hasAnnotation<SimpleCommand.Handler>() function.hasAnnotation<SimpleCommand.Handler>()
override fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array<out String> = override fun getSubCommandNames(baseCommand: AbstractReflectionCommand, function: KFunction<*>): Array<out String> =
baseCommand.names baseCommand.secondaryNames
} }
internal abstract class AbstractReflectionCommand internal abstract class AbstractReflectionCommand
@JvmOverloads constructor( @JvmOverloads constructor(
owner: CommandOwner, owner: CommandOwner,
names: Array<out String>, primaryName: String,
secondaryNames: Array<out String>,
description: String = "<no description available>", description: String = "<no description available>",
parentPermission: Permission = owner.parentPermission, parentPermission: Permission = owner.parentPermission,
prefixOptional: Boolean = false, prefixOptional: Boolean = false,
) : Command, AbstractCommand( ) : Command, AbstractCommand(
owner, owner,
names = names, primaryName = primaryName,
secondaryNames = secondaryNames,
description = description, description = description,
parentPermission = parentPermission, parentPermission = parentPermission,
prefixOptional = prefixOptional prefixOptional = prefixOptional
@ -251,7 +252,7 @@ internal fun AbstractReflectionCommand.SubCommandDescriptor.createUsage(baseComm
internal fun AbstractReflectionCommand.createSubCommand( internal fun AbstractReflectionCommand.createSubCommand(
function: KFunction<*>, function: KFunction<*>,
context: CommandArgumentContext context: CommandArgumentContext,
): AbstractReflectionCommand.SubCommandDescriptor { ): AbstractReflectionCommand.SubCommandDescriptor {
val notStatic = !function.hasAnnotation<JvmStatic>() val notStatic = !function.hasAnnotation<JvmStatic>()
//val overridePermission = null//function.findAnnotation<CompositeCommand.PermissionId>()//optional //val overridePermission = null//function.findAnnotation<CompositeCommand.PermissionId>()//optional

View File

@ -10,7 +10,6 @@
package net.mamoe.mirai.console.internal.command package net.mamoe.mirai.console.internal.command
import net.mamoe.mirai.console.command.Command import net.mamoe.mirai.console.command.Command
import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.Permission
import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService
import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Group

View File

@ -13,9 +13,9 @@ import net.mamoe.mirai.console.command.BuiltInCommands
import net.mamoe.mirai.console.command.Command import net.mamoe.mirai.console.command.Command
/** /**
* 一个权限. * 一个抽象的权限. [PermissionService] 实现不同, [Permission] 可能会有多种实例. 但一个权限总是拥有确定的 [id].
* *
* [PermissionService] 实现不同, [Permission] 可能会有多种实例. 但一个权限总是拥有确定的 [id]. * 在匹配权限时, 应使用唯一的 [id] 作为依据. 而不应该使用 [Permission] 实例. 同时, [Permission] 也不适合存储.
* *
* **注意**: 请不要手动实现这个接口. 总是从 [PermissionService.register] 获得实例. * **注意**: 请不要手动实现这个接口. 总是从 [PermissionService.register] 获得实例.
* *
@ -32,6 +32,7 @@ import net.mamoe.mirai.console.command.Command
* #### 手动申请权限 * #### 手动申请权限
* [PermissionService.register] * [PermissionService.register]
*/ */
@PermissionImplementation
public interface Permission { public interface Permission {
/** /**
* 唯一识别 ID. 所有权限的 [id] 都互不相同. * 唯一识别 ID. 所有权限的 [id] 都互不相同.
@ -49,6 +50,8 @@ public interface Permission {
/** /**
* 父权限. * 父权限.
* *
* 在检查权限时, 若一个 [Permittee] 拥有父
*
* [RootPermission] parent 为自身 * [RootPermission] parent 为自身
*/ */
public val parent: Permission public val parent: Permission

View File

@ -9,12 +9,16 @@
package net.mamoe.mirai.console.permission package net.mamoe.mirai.console.permission
import net.mamoe.mirai.console.command.Command
/** /**
* [PermissionId] 的命名空间. 用于提供 [PermissionId.namespace]. * [PermissionId] 的命名空间. 用于提供 [PermissionId.namespace].
*/ */
public interface PermissionIdNamespace { public interface PermissionIdNamespace {
/** /**
* 创建一个此命名空间下的 [PermitteeId] * 创建一个此命名空间下的 [PermitteeId].
*
* 在指令初始化时, 会申请对应权限. 此时 [name] "command.$primaryName` 其中 [primaryName][Command.primaryName].
*/ */
public fun permissionId(name: String): PermissionId public fun permissionId(name: String): PermissionId
} }

View File

@ -12,10 +12,12 @@ package net.mamoe.mirai.console.permission
import kotlin.annotation.AnnotationTarget.* import kotlin.annotation.AnnotationTarget.*
/** /**
* 表示一个应该由权限插件实现的类. * 表示一个应该由专有的权限插件 (提供 [PermissionService] 的插件) 实现的类.
* *
* 这样的类不能被用户手动实现或者继承, 也不能使用属性委托或者类委托, 或者其他任意改变实现类的手段. *
* 用户仅应该使用从 [PermissionService] 或其他途径获取这些对象, 而不能自行实现它们. * 这样的类不能被用户手动实现或者继承, 也不能使用属性委托或者类委托, 或者其他任意直接或间接实现他们的手段 (否则会导致 [PermissionService] 处理异常).
*
* 普通插件仅应该使用从 [PermissionService] 或其他途径获取这些对象.
*/ */
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR)

View File

@ -77,6 +77,8 @@ public interface PermissionService<P : Permission> {
* 申请并注册一个权限 [Permission]. * 申请并注册一个权限 [Permission].
* *
* @throws PermissionRegistryConflictException 当已存在一个 [PermissionId] 时抛出. * @throws PermissionRegistryConflictException 当已存在一个 [PermissionId] 时抛出.
*
* @return 申请到的 [Permission] 实例
*/ */
@Throws(PermissionRegistryConflictException::class) @Throws(PermissionRegistryConflictException::class)
public fun register( public fun register(
@ -90,16 +92,17 @@ public interface PermissionService<P : Permission> {
/** /**
* 授予 [permitteeId] [permission] 权限 * 授予 [permitteeId] [permission] 权限
* *
* Console 内建的权限服务支持授予操作. 但插件扩展的权限服务可能不支持. * Console 内建的权限服务支持操作. 但插件扩展的权限服务可能不支持.
* *
* @throws UnsupportedOperationException 当插件扩展的 [PermissionService] 不支持这样的操作时抛出. * @throws UnsupportedOperationException 当插件扩展的 [PermissionService] 不支持这样的操作时抛出.
*/ */
@Throws(UnsupportedOperationException::class)
public fun permit(permitteeId: PermitteeId, permission: P) public fun permit(permitteeId: PermitteeId, permission: P)
/** /**
* 撤销 [permitteeId] [permission] 授权 * 撤销 [permitteeId] [permission] 授权
* *
* Console 内建的权限服务支持授予操作. 但插件扩展的权限服务可能不支持. * Console 内建的权限服务支持操作. 但插件扩展的权限服务可能不支持.
* *
* @param recursive `true` 时递归撤销所有子权限. * @param recursive `true` 时递归撤销所有子权限.
* 例如, [permission] "*:*", * 例如, [permission] "*:*",
@ -108,6 +111,7 @@ public interface PermissionService<P : Permission> {
* *
* @throws UnsupportedOperationException 当插件扩展的 [PermissionService] 不支持这样的操作时抛出. * @throws UnsupportedOperationException 当插件扩展的 [PermissionService] 不支持这样的操作时抛出.
*/ */
@Throws(UnsupportedOperationException::class)
public fun cancel(permitteeId: PermitteeId, permission: P, recursive: Boolean) public fun cancel(permitteeId: PermitteeId, permission: P, recursive: Boolean)
public companion object { public companion object {
@ -118,6 +122,10 @@ public interface PermissionService<P : Permission> {
public val INSTANCE: PermissionService<out Permission> public val INSTANCE: PermissionService<out Permission>
get() = instanceField ?: error("PermissionService is not yet initialized therefore cannot be used.") get() = instanceField ?: error("PermissionService is not yet initialized therefore cannot be used.")
/**
* 获取一个权限, 失败时抛出 [NoSuchElementException]
*/
@Throws(NoSuchElementException::class)
public fun <P : Permission> PermissionService<P>.getOrFail(id: PermissionId): P = public fun <P : Permission> PermissionService<P>.getOrFail(id: PermissionId): P =
get(id) ?: throw NoSuchElementException("Permission not found: $id") get(id) ?: throw NoSuchElementException("Permission not found: $id")

View File

@ -37,7 +37,7 @@ public abstract class AbstractJvmPlugin @JvmOverloads constructor(
public final override val loader: JvmPluginLoader get() = super<JvmPluginInternal>.loader public final override val loader: JvmPluginLoader get() = super<JvmPluginInternal>.loader
public final override fun permissionId(name: String): PermissionId = PermissionId(description.id, "command.$name") public final override fun permissionId(name: String): PermissionId = PermissionId(description.id, name)
/** /**
* 重载 [PluginData] * 重载 [PluginData]

View File

@ -16,7 +16,6 @@ import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.MiraiConsole
import net.mamoe.mirai.console.command.BuiltInCommands import net.mamoe.mirai.console.command.BuiltInCommands
import net.mamoe.mirai.console.command.Command.Companion.primaryName
import net.mamoe.mirai.console.command.CommandExecuteStatus import net.mamoe.mirai.console.command.CommandExecuteStatus
import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandManager
import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand