From a13ce6ff1708fb14563c04ee006f89cad66bd099 Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 11 Sep 2020 23:05:00 +0800 Subject: [PATCH 01/14] Redesign extensions; Introduce ComponentStorage; Add receiver ScopedComponentStorage to JvmPlugin; Remove dynamic registers for PluginLoader; Redesign plugin load flow; --- .../net/mamoe/mirai/console/MiraiConsole.kt | 8 +- .../console/extension/ComponentStorage.kt | 218 ++++++++++++++++++ .../mirai/console/extension/Extension.kt | 1 + .../mirai/console/extension/ExtensionPoint.kt | 102 +------- .../console/extension/ExtensionRegistry.kt | 19 -- .../extensions/PermissionServiceProvider.kt | 11 +- .../extensions/PluginLoaderProvider.kt | 3 - .../extensions/SingletonExtensionSelector.kt | 37 ++- .../MiraiConsoleImplementationBridge.kt | 66 ++++-- .../BuiltInSingletonExtensionSelector.kt | 11 +- .../internal/plugin/JarPluginLoaderImpl.kt | 6 +- .../internal/plugin/JvmPluginInternal.kt | 15 +- .../internal/plugin/PluginManagerImpl.kt | 134 +++++------ .../console/permission/PermissionService.kt | 10 +- .../net/mamoe/mirai/console/plugin/Plugin.kt | 6 - .../mirai/console/plugin/PluginLoader.kt | 4 - .../mirai/console/plugin/PluginManager.kt | 20 -- .../plugin/description/PluginDescription.kt | 7 - .../plugin/description/PluginLoadPriority.kt | 59 ----- .../console/plugin/jvm/AbstractJvmPlugin.kt | 47 +++- .../mirai/console/plugin/jvm/JvmPlugin.kt | 71 ++---- .../plugin/jvm/JvmPluginDescription.kt | 31 +-- 22 files changed, 447 insertions(+), 439 deletions(-) create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt delete mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionRegistry.kt delete mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginLoadPriority.kt diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index 19707ba29..e82df754f 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -18,7 +18,7 @@ import kotlinx.coroutines.Job import net.mamoe.mirai.Bot import net.mamoe.mirai.console.MiraiConsole.INSTANCE import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start -import net.mamoe.mirai.console.extension.foldExtensions +import net.mamoe.mirai.console.extension.GlobalComponentStorage import net.mamoe.mirai.console.extensions.BotConfigurationAlterer import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge import net.mamoe.mirai.console.plugin.PluginLoader @@ -133,8 +133,10 @@ public interface MiraiConsole : CoroutineScope { configuration() } - config = BotConfigurationAlterer.foldExtensions(config) { acc, extension -> - extension.alterConfiguration(id, acc) + config = GlobalComponentStorage.run { + BotConfigurationAlterer.foldExtensions(config) { acc, extension -> + extension.alterConfiguration(id, acc) + } } return when (password) { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt new file mode 100644 index 000000000..e7ffcc587 --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt @@ -0,0 +1,218 @@ +@file:Suppress("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") + +package net.mamoe.mirai.console.extension + +import net.mamoe.mirai.console.extensions.LazyPermissionServiceProviderImpl +import net.mamoe.mirai.console.extensions.PermissionServiceProvider +import net.mamoe.mirai.console.extensions.SingletonExtensionSelector +import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton +import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip +import net.mamoe.mirai.console.permission.ExperimentalPermission +import net.mamoe.mirai.console.permission.PermissionService +import net.mamoe.mirai.console.plugin.Plugin +import net.mamoe.mirai.console.plugin.name +import java.util.concurrent.ConcurrentHashMap +import java.util.concurrent.CopyOnWriteArraySet +import kotlin.contracts.contract +import kotlin.internal.LowPriorityInOverloadResolution +import kotlin.reflect.KClass +import kotlin.reflect.full.companionObjectInstance + +/** + * 组件容器, 容纳 [Plugin] 注册的 [Extension]. + */ +public interface ComponentStorage { + public fun contribute( + extensionPoint: ExtensionPoint, + plugin: Plugin, + extensionInstance: T, + ) + + public fun contribute( + extensionPoint: ExtensionPoint, + plugin: Plugin, + lazyInstance: () -> T, + ) +} + +@Suppress("EXPOSED_SUPER_CLASS") +public class ScopedComponentStorage( + @JvmField + internal val plugin: Plugin, +) : AbstractConcurrentComponentStorage() { + /** + * 注册一个扩展 + */ + public fun contribute( + extensionPoint: ExtensionPoint, + lazyInstance: () -> E, + ) { + contribute(extensionPoint, plugin, lazyInstance) + } + + /** + * 注册一个扩展 + */ + public inline fun contribute( + noinline lazyInstance: () -> E, + ) { + @Suppress("UNCHECKED_CAST") + (contribute( + (E::class.companionObjectInstance as? ExtensionPoint + ?: error("Companion object of ${E::class.qualifiedName} is not an ExtensionPoint")), + lazyInstance + )) + } + + /** + * 注册一个扩展 + */ + @ExperimentalPermission + public fun contributePermissionService( + lazyInstance: () -> PermissionService<*>, + ) { + contribute(PermissionServiceProvider, plugin, LazyPermissionServiceProviderImpl(lazyInstance)) + } +} + +internal object GlobalComponentStorage : AbstractConcurrentComponentStorage() + +internal interface ExtensionRegistry { + val plugin: Plugin + val extension: E + + operator fun component1(): Plugin { + return this.plugin + } + + operator fun component2(): E { + return this.extension + } +} + +internal class LazyExtensionRegistry( + override val plugin: Plugin, + initializer: () -> E, +) : ExtensionRegistry { + override val extension: E by lazy { initializer() } +} + +internal data class DataExtensionRegistry( + override val plugin: Plugin, + override val extension: E, +) : ExtensionRegistry + +internal abstract class AbstractConcurrentComponentStorage : ComponentStorage { + @Suppress("UNCHECKED_CAST") + internal fun ExtensionPoint.getExtensions(): Set> { + return instances.getOrPut(this, ::CopyOnWriteArraySet) as Set> + } + + internal fun mergeWith(another: AbstractConcurrentComponentStorage) { + for ((ep, list) in another.instances) { + for (extensionRegistry in list) { + @Suppress("UNCHECKED_CAST") + ep as ExtensionPoint + this.contribute(ep, extensionRegistry.plugin, lazyInstance = { extensionRegistry.extension }) + } + } + } + + internal inline fun ExtensionPoint.withExtensions(block: T.() -> Unit) { + return withExtensions { _ -> block() } + } + + @LowPriorityInOverloadResolution + internal inline fun ExtensionPoint.withExtensions(block: T.(plugin: Plugin) -> Unit) { + contract { + callsInPlace(block) + } + for ((plugin, extension) in this.getExtensions()) { + kotlin.runCatching { + block.invoke(extension, plugin) + }.getOrElse { throwable -> + throwExtensionException(extension, plugin, throwable) + } + } + } + + internal inline fun > ExtensionPoint.findSingleton(builtin: E): E = + findSingleton(E::class, builtin) + + internal fun > ExtensionPoint.findSingleton(type: KClass, builtin: E): E { + val candidates = this.getExtensions() + return when (candidates.size) { + 0 -> builtin + 1 -> candidates.single().extension + else -> SingletonExtensionSelector.instance.selectSingleton(type, candidates) ?: builtin + } + } + + internal inline fun , T> ExtensionPoint.findSingletonInstance(builtin: T): T = + findSingletonInstance(E::class, builtin) + + internal fun , T> ExtensionPoint.findSingletonInstance( + type: KClass, + builtin: T, + ): T { + val candidates = this.getExtensions() + return when (candidates.size) { + 0 -> builtin + 1 -> candidates.single().extension.instance + else -> SingletonExtensionSelector.instance.selectSingleton(type, candidates)?.instance ?: builtin + } + } + + internal inline fun ExtensionPoint.foldExtensions( + initial: E, + block: (acc: E, extension: T) -> E, + ): E { + contract { + callsInPlace(block) + } + var e: E = initial + for ((plugin, extension) in this.getExtensions()) { + kotlin.runCatching { + e = block.invoke(e, extension) + }.getOrElse { throwable -> + throwExtensionException(extension, plugin, throwable) + } + } + return e + } + + internal fun ExtensionPoint.throwExtensionException( + extension: T, + plugin: Plugin, + throwable: Throwable, + ) { + throw ExtensionException( + "Exception while executing extension ${extension.kClassQualifiedNameOrTip} provided by plugin '${plugin.name}', registered for ${this.type.qualifiedName}", + throwable + ) + } + + internal inline fun ExtensionPoint.useExtensions(block: (extension: T) -> Unit): Unit = + withExtensions(block) + + @LowPriorityInOverloadResolution + internal inline fun ExtensionPoint.useExtensions(block: (extension: T, plugin: Plugin) -> Unit): Unit = + withExtensions(block) + + val instances: MutableMap, MutableSet>> = ConcurrentHashMap() + override fun contribute( + extensionPoint: ExtensionPoint, + plugin: Plugin, + extensionInstance: T, + ) { + instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(DataExtensionRegistry(plugin, extensionInstance)) + } + + override fun contribute( + extensionPoint: ExtensionPoint, + plugin: Plugin, + lazyInstance: () -> T, + ) { + instances.getOrPut(extensionPoint, ::CopyOnWriteArraySet).add(LazyExtensionRegistry(plugin, lazyInstance)) + } +} diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt index 0f1963954..62705a203 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt @@ -12,6 +12,7 @@ package net.mamoe.mirai.console.extension import net.mamoe.mirai.console.extensions.PermissionServiceProvider import net.mamoe.mirai.console.extensions.PluginLoaderProvider import net.mamoe.mirai.console.extensions.SingletonExtensionSelector +import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton import net.mamoe.mirai.console.util.ConsoleExperimentalAPI /** diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt index ebb30b3ec..8a35055bb 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt @@ -11,16 +11,8 @@ package net.mamoe.mirai.console.extension -import net.mamoe.mirai.console.extensions.SingletonExtensionSelector -import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip -import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.PluginLoader -import net.mamoe.mirai.console.plugin.name import net.mamoe.mirai.console.util.ConsoleExperimentalAPI -import java.util.* -import java.util.concurrent.CopyOnWriteArraySet -import kotlin.contracts.contract -import kotlin.internal.LowPriorityInOverloadResolution import kotlin.reflect.KClass import kotlin.reflect.full.isSubclassOf @@ -28,9 +20,6 @@ import kotlin.reflect.full.isSubclassOf public interface ExtensionPoint { public val type: KClass - public fun registerExtension(plugin: Plugin, extension: T) - public fun getExtensions(): Set> - public companion object { @JvmStatic @JvmSynthetic @@ -44,15 +33,7 @@ public interface ExtensionPoint { } @ConsoleExperimentalAPI -public interface SingletonExtensionPoint> : ExtensionPoint { - public companion object { - @JvmStatic - @ConsoleExperimentalAPI - public fun > SingletonExtensionPoint.findSingleton(): T? { - return SingletonExtensionSelector.selectSingleton(type, this.getExtensions()) - } - } -} +public interface SingletonExtensionPoint> : ExtensionPoint /** * 表示一个扩展点 @@ -60,29 +41,8 @@ public interface SingletonExtensionPoint> : ExtensionP @ConsoleExperimentalAPI public open class AbstractExtensionPoint( @ConsoleExperimentalAPI - public override val type: KClass -) : ExtensionPoint { - init { - @Suppress("LeakingThis") - allExtensionPoints.add(this) - } - - private val instances: MutableSet> = CopyOnWriteArraySet() - - @ConsoleExperimentalAPI - public override fun registerExtension(plugin: Plugin, extension: T) { - // require(plugin.isEnabled) { "Plugin $plugin must be enabled before registering an extension." } - requireNotNull(extension::class.qualifiedName) { "Extension must not be an anonymous object" } - instances.add(ExtensionRegistry(plugin, extension)) - } - - public override fun getExtensions(): Set> = Collections.unmodifiableSet(instances) - - internal companion object { - @ConsoleExperimentalAPI - internal val allExtensionPoints: MutableList> = mutableListOf() - } -} + public override val type: KClass, +) : ExtensionPoint /** @@ -99,58 +59,4 @@ public open class ExtensionException : RuntimeException { public constructor(message: String?) : super(message) public constructor(message: String?, cause: Throwable?) : super(message, cause) public constructor(cause: Throwable?) : super(cause) -} - -internal inline fun AbstractExtensionPoint.withExtensions(block: T.() -> Unit) { - return withExtensions { _ -> block() } -} - -@LowPriorityInOverloadResolution -internal inline fun AbstractExtensionPoint.withExtensions(block: T.(plugin: Plugin) -> Unit) { - contract { - callsInPlace(block) - } - for ((plugin, extension) in this.getExtensions()) { - kotlin.runCatching { - block.invoke(extension, plugin) - }.getOrElse { throwable -> - throwExtensionException(extension, plugin, throwable) - } - } -} - -internal inline fun AbstractExtensionPoint.foldExtensions( - initial: E, - block: (acc: E, extension: T) -> E -): E { - contract { - callsInPlace(block) - } - var e: E = initial - for ((plugin, extension) in this.getExtensions()) { - kotlin.runCatching { - e = block.invoke(e, extension) - }.getOrElse { throwable -> - throwExtensionException(extension, plugin, throwable) - } - } - return e -} - -internal fun AbstractExtensionPoint.throwExtensionException( - extension: T, - plugin: Plugin, - throwable: Throwable -) { - throw ExtensionException( - "Exception while executing extension ${extension.kClassQualifiedNameOrTip} provided by plugin '${plugin.name}', registered for ${this.type.qualifiedName}", - throwable - ) -} - -internal inline fun AbstractExtensionPoint.useExtensions(block: (extension: T) -> Unit): Unit = - withExtensions(block) - -@LowPriorityInOverloadResolution -internal inline fun AbstractExtensionPoint.useExtensions(block: (extension: T, plugin: Plugin) -> Unit): Unit = - withExtensions(block) \ No newline at end of file +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionRegistry.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionRegistry.kt deleted file mode 100644 index d79b1cdf3..000000000 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionRegistry.kt +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.console.extension - -import net.mamoe.mirai.console.plugin.Plugin -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI - -@ConsoleExperimentalAPI -public data class ExtensionRegistry( - public val plugin: Plugin, - public val extension: T -) \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt index 8a7a415e3..f0a8308c2 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt @@ -5,18 +5,23 @@ import net.mamoe.mirai.console.extension.SingletonExtension import net.mamoe.mirai.console.extension.SingletonExtensionPoint import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionService -import net.mamoe.mirai.console.plugin.description.PluginLoadPriority /** * [权限服务][PermissionService] 提供器. * * 当插件注册 [PermissionService] 后, 默认会使用插件的 [PermissionService]. - * - * 此扩展可由 [PluginLoadPriority.BEFORE_EXTENSIONS] 和 [PluginLoadPriority.ON_EXTENSIONS] 插件提供 */ @ExperimentalPermission public interface PermissionServiceProvider : SingletonExtension> { public companion object ExtensionPoint : AbstractExtensionPoint(PermissionServiceProvider::class), SingletonExtensionPoint +} + +@ExperimentalPermission +public class PermissionServiceProviderImpl(override val instance: PermissionService<*>) : PermissionServiceProvider + +@ExperimentalPermission +public class LazyPermissionServiceProviderImpl(initializer: () -> PermissionService<*>) : PermissionServiceProvider { + override val instance: PermissionService<*> by lazy(initializer) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PluginLoaderProvider.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PluginLoaderProvider.kt index 0905229a5..cf2271981 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PluginLoaderProvider.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PluginLoaderProvider.kt @@ -3,12 +3,9 @@ package net.mamoe.mirai.console.extensions import net.mamoe.mirai.console.extension.AbstractExtensionPoint import net.mamoe.mirai.console.extension.InstanceExtension import net.mamoe.mirai.console.plugin.PluginLoader -import net.mamoe.mirai.console.plugin.description.PluginLoadPriority /** * 提供扩展 [PluginLoader] - * - * 此扩展可由 [PluginLoadPriority.BEFORE_EXTENSIONS] 插件提供 */ public interface PluginLoaderProvider : InstanceExtension> { public companion object ExtensionPoint : AbstractExtensionPoint(PluginLoaderProvider::class) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt index fdaf4a2c5..49adf4239 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt @@ -12,8 +12,9 @@ package net.mamoe.mirai.console.extensions import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.extension.* import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector -import net.mamoe.mirai.console.plugin.description.PluginLoadPriority +import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.name +import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.utils.info import kotlin.reflect.KClass @@ -21,21 +22,33 @@ import kotlin.reflect.KClass * 用于同时拥有多个 [SingletonExtension] 时选择一个实例. * * 如有多个 [SingletonExtensionSelector] 注册, 将会停止服务器. - * - * 此扩展可由 [PluginLoadPriority.BEFORE_EXTENSIONS] 插件提供 */ +@ConsoleExperimentalAPI public interface SingletonExtensionSelector : FunctionExtension { + public data class Registry( + val plugin: Plugin, + val extension: T, + ) + /** + * @return null 表示使用 builtin + */ public fun selectSingleton( extensionType: KClass, - candidates: Collection> + candidates: Collection>, ): T? public companion object ExtensionPoint : AbstractExtensionPoint(SingletonExtensionSelector::class) { - internal val instance: SingletonExtensionSelector by lazy { - val instances = SingletonExtensionSelector.getExtensions() - when { + + private var instanceField: SingletonExtensionSelector? = null + + internal val instance: SingletonExtensionSelector get() = instanceField ?: error("") + + internal fun init() { + check(instanceField == null) { "Internal error: reinitialize SingletonExtensionSelector" } + val instances = GlobalComponentStorage.run { SingletonExtensionSelector.getExtensions() } + instanceField = when { instances.isEmpty() -> BuiltInSingletonExtensionSelector instances.size == 1 -> { instances.single().also { (plugin, ext) -> @@ -50,8 +63,14 @@ public interface SingletonExtensionSelector : FunctionExtension { internal fun selectSingleton( extensionType: KClass, - candidates: Collection> + candidates: Collection>, ): T? = - instance.selectSingleton(extensionType, candidates) + instance.selectSingleton(extensionType, candidates.map { Registry(it.plugin, it.extension) }) + + + internal fun SingletonExtensionSelector.selectSingleton( + extensionType: KClass, + candidates: Collection>, + ): T? = selectSingleton(extensionType, candidates.map { Registry(it.plugin, it.extension) }) } } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt index 8f7c529c9..a15c3955c 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt @@ -27,12 +27,14 @@ import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.ConsoleCommandSender import net.mamoe.mirai.console.data.PluginDataStorage -import net.mamoe.mirai.console.extension.useExtensions +import net.mamoe.mirai.console.extension.GlobalComponentStorage +import net.mamoe.mirai.console.extensions.PermissionServiceProvider import net.mamoe.mirai.console.extensions.PostStartupExtension import net.mamoe.mirai.console.extensions.SingletonExtensionSelector import net.mamoe.mirai.console.internal.command.CommandManagerImpl import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig import net.mamoe.mirai.console.internal.data.builtins.ConsoleDataScope +import net.mamoe.mirai.console.internal.data.castOrNull import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl import net.mamoe.mirai.console.internal.util.autoHexToBytes @@ -44,6 +46,7 @@ import net.mamoe.mirai.console.permission.RootPermission import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.center.PluginCenter +import net.mamoe.mirai.console.plugin.jvm.AbstractJvmPlugin import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.console.util.ConsoleInput import net.mamoe.mirai.utils.* @@ -124,35 +127,48 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI ConsoleDataScope.reloadAll() } - val pluginLoadSession: PluginManagerImpl.PluginLoadSession - - phase `load BEFORE_EXTENSIONS plugins`@{ + phase `initialize all plugins`@{ PluginManager // init - mainLogger.verbose { "Loading PluginLoader provider plugins..." } - PluginManagerImpl.loadEnablePluginProviderPlugins() - mainLogger.verbose { "${PluginManager.plugins.size} such plugin(s) loaded." } + mainLogger.verbose { "Loading JVM plugins..." } + PluginManagerImpl.loadAllPluginsUsingBuiltInLoaders() + PluginManagerImpl.initExternalPluginLoaders().let { count -> + mainLogger.verbose { "$count external PluginLoader(s) found. " } + if (count != 0) { + mainLogger.verbose { "Loading external plugins..." } + } + } + } + + phase `load all plugins`@{ + PluginManagerImpl.loadPlugins(PluginManagerImpl.scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider()) + + mainLogger.verbose { "${PluginManager.plugins.size} plugin(s) loaded." } + } + + phase `collect extensions`@{ + for (resolvedPlugin in PluginManagerImpl.resolvedPlugins) { + resolvedPlugin.castOrNull()?.let { + GlobalComponentStorage.mergeWith(it.componentStorage) + } + } } phase `load SingletonExtensionSelector`@{ + SingletonExtensionSelector.init() val instance = SingletonExtensionSelector.instance if (instance is BuiltInSingletonExtensionSelector) { ConsoleDataScope.addAndReloadConfig(instance.config) } } - phase `load ON_EXTENSIONS plugins`@{ - mainLogger.verbose { "Scanning high-priority extension and normal plugins..." } - pluginLoadSession = PluginManagerImpl.scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider() - mainLogger.verbose { "${pluginLoadSession.allKindsOfPlugins.size} plugin(s) found." } - - mainLogger.verbose { "Loading Extension provider plugins..." } - PluginManagerImpl.loadEnableHighPriorityExtensionPlugins(pluginLoadSession) - mainLogger.verbose { "${PluginManager.plugins.size} such plugin(s) loaded." } - } - phase `load PermissionService`@{ mainLogger.verbose { "Loading PermissionService..." } + + PermissionService.instanceField = GlobalComponentStorage.run { + PermissionServiceProvider.findSingletonInstance(BuiltInPermissionService) + } + PermissionService.INSTANCE.let { ps -> if (ps is BuiltInPermissionService) { ConsoleDataScope.addAndReloadConfig(ps.config) @@ -171,13 +187,13 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI CommandManagerImpl.commandListener // start } - phase `load AFTER_EXTENSION plugins`@{ - mainLogger.verbose { "Loading normal plugins..." } - val count = PluginManagerImpl.loadEnableNormalPlugins(pluginLoadSession) - mainLogger.verbose { "$count normal plugin(s) loaded." } - } + phase `enable plugins`@{ + mainLogger.verbose { "Enabling plugins..." } - mainLogger.info { "${PluginManagerImpl.plugins.size} plugin(s) loaded." } + PluginManagerImpl.enableAllLoadedPlugins() + + mainLogger.info { "${PluginManagerImpl.plugins.size} plugin(s) enabled." } + } phase `auto-login bots`@{ runBlocking { @@ -198,7 +214,9 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI } } - PostStartupExtension.useExtensions { it() } + GlobalComponentStorage.run { + PostStartupExtension.useExtensions { it() } + } mainLogger.info { "mirai-console started successfully." } } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extensions/BuiltInSingletonExtensionSelector.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extensions/BuiltInSingletonExtensionSelector.kt index 8621e0c01..5308ba4a3 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extensions/BuiltInSingletonExtensionSelector.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/extensions/BuiltInSingletonExtensionSelector.kt @@ -5,7 +5,6 @@ import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.data.AutoSavePluginConfig import net.mamoe.mirai.console.data.value import net.mamoe.mirai.console.extension.Extension -import net.mamoe.mirai.console.extension.ExtensionRegistry import net.mamoe.mirai.console.extensions.SingletonExtensionSelector import net.mamoe.mirai.console.internal.data.kClassQualifiedName import net.mamoe.mirai.console.plugin.name @@ -25,7 +24,7 @@ internal object BuiltInSingletonExtensionSelector : SingletonExtensionSelector { override fun selectSingleton( extensionType: KClass, - candidates: Collection> + candidates: Collection>, ): T? = when { candidates.isEmpty() -> null candidates.size == 1 -> candidates.single().extension @@ -42,14 +41,14 @@ internal object BuiltInSingletonExtensionSelector : SingletonExtensionSelector { private fun promptForSelectionAndSave( extensionType: KClass, - candidates: Collection> + candidates: Collection>, ) = promptForManualSelection(extensionType, candidates) .also { config.value[extensionType.qualifiedName!!] = it.extension.kClassQualifiedName!! }.extension - private fun promptForManualSelection( + private fun promptForManualSelection( extensionType: KClass, - candidates: Collection> - ): ExtensionRegistry { + candidates: Collection>, + ): SingletonExtensionSelector.Registry { MiraiConsole.mainLogger.info { "There are multiple ${extensionType.simpleName}s, please select one:" } val candidatesList = candidates.toList() diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JarPluginLoaderImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JarPluginLoaderImpl.kt index fbeb7d048..c1432d4a4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JarPluginLoaderImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JarPluginLoaderImpl.kt @@ -84,10 +84,10 @@ internal object JarPluginLoaderImpl : @Throws(PluginLoadException::class) override fun load(plugin: JvmPlugin) { ensureActive() + runCatching { - if (plugin is JvmPluginInternal) { - plugin.internalOnLoad() - } else plugin.onLoad() + check(plugin is JvmPluginInternal) { "A JvmPlugin must extend AbstractJvmPlugin" } + plugin.internalOnLoad(plugin.componentStorage) }.getOrElse { throw PluginLoadException("Exception while loading ${plugin.description.name}", it) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt index 80129ef53..b0afc3348 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/JvmPluginInternal.kt @@ -14,6 +14,7 @@ import kotlinx.atomicfu.locks.withLock import kotlinx.coroutines.* import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.data.runCatchingLog +import net.mamoe.mirai.console.extension.ScopedComponentStorage import net.mamoe.mirai.console.internal.data.mkdir import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission @@ -24,7 +25,9 @@ import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader import net.mamoe.mirai.console.plugin.ResourceContainer.Companion.asResourceContainer +import net.mamoe.mirai.console.plugin.jvm.AbstractJvmPlugin import net.mamoe.mirai.console.plugin.jvm.JvmPlugin +import net.mamoe.mirai.console.plugin.jvm.JvmPlugin.Companion.onLoad import net.mamoe.mirai.console.plugin.name import net.mamoe.mirai.console.util.NamedSupervisorJob import net.mamoe.mirai.utils.MiraiLogger @@ -41,9 +44,12 @@ internal val T.job: Job where T : CoroutineScope, T : Plugin get() = this.co */ @PublishedApi internal abstract class JvmPluginInternal( - parentCoroutineContext: CoroutineContext + parentCoroutineContext: CoroutineContext, ) : JvmPlugin, CoroutineScope { + @Suppress("LeakingThis") + internal val componentStorage: ScopedComponentStorage = ScopedComponentStorage(this) + @OptIn(ExperimentalPermission::class) final override val parentPermission: Permission by lazy { PermissionService.INSTANCE.register( @@ -106,8 +112,8 @@ internal abstract class JvmPluginInternal( } @Throws(Throwable::class) - internal fun internalOnLoad() { // propagate exceptions - onLoad() + internal fun internalOnLoad(componentStorage: ScopedComponentStorage) { + onLoad(componentStorage) } internal fun internalOnEnable(): Boolean { @@ -135,6 +141,7 @@ internal abstract class JvmPluginInternal( // for future use @Suppress("PropertyName") internal val _intrinsicCoroutineContext: CoroutineContext by lazy { + this as AbstractJvmPlugin CoroutineName("Plugin $dataHolderName") } @@ -149,7 +156,7 @@ internal abstract class JvmPluginInternal( .plus(parentCoroutineContext) .plus( NamedSupervisorJob( - "Plugin $dataHolderName", + "Plugin ${(this as AbstractJvmPlugin).dataHolderName}", parentCoroutineContext[Job] ?: JarPluginLoaderImpl.coroutineContext[Job]!! ) ) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt index 160df275a..8694bb37b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/plugin/PluginManagerImpl.kt @@ -11,24 +11,22 @@ package net.mamoe.mirai.console.internal.plugin -import kotlinx.atomicfu.locks.withLock import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import net.mamoe.mirai.console.MiraiConsole -import net.mamoe.mirai.console.extension.useExtensions +import net.mamoe.mirai.console.extension.GlobalComponentStorage import net.mamoe.mirai.console.extensions.PluginLoaderProvider import net.mamoe.mirai.console.internal.data.cast import net.mamoe.mirai.console.internal.data.mkdir import net.mamoe.mirai.console.plugin.* import net.mamoe.mirai.console.plugin.description.PluginDependency import net.mamoe.mirai.console.plugin.description.PluginDescription -import net.mamoe.mirai.console.plugin.description.PluginLoadPriority import net.mamoe.mirai.console.plugin.jvm.JvmPlugin import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope import net.mamoe.mirai.utils.info import java.io.File import java.nio.file.Path -import java.util.concurrent.locks.ReentrantLock +import java.util.concurrent.CopyOnWriteArrayList internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsole.childScope("PluginManager") { @@ -43,11 +41,11 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol private val _pluginLoaders: MutableList> by lazy { MiraiConsole.builtInPluginLoaders.toMutableList() } - private val loadersLock: ReentrantLock = ReentrantLock() private val logger = MiraiConsole.createLogger("plugin") @JvmField - internal val resolvedPlugins: MutableList = mutableListOf() + internal val resolvedPlugins: MutableList = + CopyOnWriteArrayList() // write operations are mostly performed on init override val plugins: List get() = resolvedPlugins.toList() override val builtInLoaders: List> @@ -64,17 +62,6 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol ?: error("Plugin is unloaded") - override fun PluginLoader<*, *>.register(): Boolean = loadersLock.withLock { - if (_pluginLoaders.any { it::class == this::class }) { - return false - } - _pluginLoaders.add(this) - } - - override fun PluginLoader<*, *>.unregister() = loadersLock.withLock { - _pluginLoaders.remove(this) - } - init { MiraiConsole.coroutineContext[Job]!!.invokeOnCompletion { plugins.forEach { it.disable() } @@ -114,59 +101,65 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol } internal class PluginLoadSession( - val allKindsOfPlugins: List, List>> + val allKindsOfPlugins: List, ) - // Phase #2 - internal fun scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider(): PluginLoadSession { - return PluginLoadSession(loadersLock.withLock { _pluginLoaders.listAllPlugins() }) + /////////////////////////////////////////////////////////////////////////// + // Phase #0: + // - initialize all plugins using builtin loaders + // - sort by dependencies + /////////////////////////////////////////////////////////////////////////// + + /** + * 使用 [builtInLoaders] 寻找所有插件, 并初始化其主类. + */ + @Suppress("UNCHECKED_CAST") + @Throws(PluginMissingDependencyException::class) + private fun findAndSortAllPluginsUsingBuiltInLoaders(): List { + val allDescriptions = + builtInLoaders.listAndSortAllPlugins() + .asSequence() + .onEach { (_, descriptions) -> + descriptions.let(PluginManagerImpl::checkPluginDescription) + } + + return allDescriptions.toList().sortByDependencies() } - // Phase #0 - internal fun loadEnablePluginProviderPlugins() { - loadAndEnableLoaderProvidersUsingBuiltInLoaders() - } - - // Phase #3 - internal fun loadEnableHighPriorityExtensionPlugins(session: PluginLoadSession): Int { - loadersLock.withLock { - session.allKindsOfPlugins.flatMap { it.second } - .filter { it.loadPriority == PluginLoadPriority.ON_EXTENSIONS } - .sortByDependencies() - .also { it.loadAndEnableAllInOrder() } - .let { return it.size } + internal fun loadAllPluginsUsingBuiltInLoaders() { + for ((l, _, p) in findAndSortAllPluginsUsingBuiltInLoaders()) { + l.load(p) } } - // Phase #4 - internal fun loadEnableNormalPlugins(session: PluginLoadSession): Int { - loadersLock.withLock { - session.allKindsOfPlugins.flatMap { it.second } - .filter { it.loadPriority == PluginLoadPriority.AFTER_EXTENSIONS } - .sortByDependencies() - .also { it.loadAndEnableAllInOrder() } - .let { return it.size } - } - } + /////////////////////////////////////////////////////////////////////////// + // Phase #1: + // - load PluginLoaderProvider + /////////////////////////////////////////////////////////////////////////// - // Phase #1 - internal fun loadPluginLoaderProvidedByPlugins() { - loadersLock.withLock { + internal fun initExternalPluginLoaders(): Int { + var count = 0 + GlobalComponentStorage.run { PluginLoaderProvider.useExtensions { ext, plugin -> logger.info { "Loaded PluginLoader ${ext.instance} from ${plugin.name}" } _pluginLoaders.add(ext.instance) + count++ } } + return count } + // Phase #2 + internal fun scanPluginsUsingPluginLoadersIncludingThoseFromPluginLoaderProvider(): PluginLoadSession { + return PluginLoadSession(_pluginLoaders.filterNot { builtInLoaders.contains(it) }.listAndSortAllPlugins()) + } - private fun List.loadAndEnableAllInOrder() { - this.forEach { (loader, _, plugin) -> - loader.loadPluginNoEnable(plugin) - } - this.forEach { (loader, _, plugin) -> - loader.enablePlugin(plugin) - } + internal fun loadPlugins(session: PluginLoadSession) { + session.allKindsOfPlugins.forEach { it.loader.load(it.plugin) } + } + + internal fun enableAllLoadedPlugins() { + resolvedPlugins.forEach { it.enable() } } @kotlin.jvm.Throws(PluginLoadException::class) @@ -178,31 +171,10 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol } } - /** - * @return [builtInLoaders] 可以加载的插件. 已经完成了 [PluginLoader.load], 但没有 [PluginLoader.enable] - */ - @Suppress("UNCHECKED_CAST") - @Throws(PluginMissingDependencyException::class) - private fun loadAndEnableLoaderProvidersUsingBuiltInLoaders(): List { - val allDescriptions = - builtInLoaders.listAllPlugins() - .asSequence() - .onEach { (loader, descriptions) -> - loader as PluginLoader - - descriptions.forEach(PluginManagerImpl::checkPluginDescription) - descriptions.filter { it.loadPriority == PluginLoadPriority.BEFORE_EXTENSIONS }.sortByDependencies() - .loadAndEnableAllInOrder() - } - .flatMap { it.second.asSequence() } - - return allDescriptions.toList() - } - - private fun List>.listAllPlugins(): List, List>> { - return associateWith { loader -> + private fun List>.listAndSortAllPlugins(): List { + return flatMap { loader -> loader.listPlugins().map { plugin -> plugin.description.wrapWith(loader, plugin) } - }.toList() + }.sortByDependencies() } @Throws(PluginMissingDependencyException::class) @@ -220,7 +192,7 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol fun Collection.filterIsMissing(): List = this.filterNot { it.isOptional || it in resolved } - tailrec fun List.doSort() { + fun List.doSort() { if (this.isEmpty()) return val beforeSize = this.size @@ -239,14 +211,12 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol this.doSort() return resolved } - - // endregion } internal data class PluginDescriptionWithLoader( @JvmField val loader: PluginLoader, // easier type @JvmField val delegate: PluginDescription, - @JvmField val plugin: Plugin + @JvmField val plugin: Plugin, ) : PluginDescription by delegate @Suppress("UNCHECKED_CAST") diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt index 0b935e6f5..cef6b07de 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt @@ -11,7 +11,6 @@ package net.mamoe.mirai.console.permission -import net.mamoe.mirai.console.extension.SingletonExtensionPoint.Companion.findSingleton import net.mamoe.mirai.console.extensions.PermissionServiceProvider import kotlin.reflect.KClass import kotlin.reflect.full.isSuperclassOf @@ -47,7 +46,7 @@ public interface PermissionService

{ public fun register( id: PermissionId, description: String, - parent: Permission = RootPermission + parent: Permission = RootPermission, ): P /////////////////////////////////////////////////////////////////////////// @@ -56,11 +55,12 @@ public interface PermissionService

{ public fun deny(permissibleIdentifier: PermissibleIdentifier, permission: P) public companion object { + internal var instanceField: PermissionService<*>? = null + @get:JvmName("getInstance") @JvmStatic - public val INSTANCE: PermissionService by lazy { - PermissionServiceProvider.findSingleton()?.instance ?: BuiltInPermissionService - } + public val INSTANCE: PermissionService + get() = instanceField ?: error("PermissionService is not yet initialized therefore cannot be used.") public fun

PermissionService

.getOrFail(id: PermissionId): P = get(id) ?: throw PermissionNotFoundException(id) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt index 17155dcd3..d0f95888c 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/Plugin.kt @@ -18,7 +18,6 @@ import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.safeLoader import net.mamoe.mirai.console.plugin.description.PluginDependency import net.mamoe.mirai.console.plugin.description.PluginDescription -import net.mamoe.mirai.console.plugin.description.PluginLoadPriority import net.mamoe.mirai.console.plugin.jvm.JvmPlugin /** @@ -64,11 +63,6 @@ public inline val Plugin.name: String get() = this.description.name */ public inline val Plugin.version: Semver get() = this.description.version -/** - * 获取 [PluginDescription.loadPriority] - */ -public inline val Plugin.loadPriority: PluginLoadPriority get() = this.description.loadPriority - /** * 获取 [PluginDescription.info] */ diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt index f83a5f12e..141cff9ad 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginLoader.kt @@ -13,7 +13,6 @@ package net.mamoe.mirai.console.plugin import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.disable import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.enable -import net.mamoe.mirai.console.plugin.PluginManager.INSTANCE.register import net.mamoe.mirai.console.plugin.description.PluginDescription import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import java.io.File @@ -31,14 +30,11 @@ import java.util.* * * ## 扩展加载器 * 插件被允许扩展一个加载器. - * Console 使用 [ServiceLoader] 加载 [PluginLoader] 的实例. - * 插件也可通过 [PluginManager.register] 手动注册, 然而这是不推荐的. * * ### 实现扩展加载器 * 直接实现接口 [PluginLoader] 或 [FilePluginLoader], 并添加 [ServiceLoader] 相关资源文件即可. * * @see JarPluginLoader Jar 插件加载器 - * @see PluginManager.register 注册一个扩展的插件加载器 */ public interface PluginLoader

{ /** diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt index 9f7820129..6b8970099 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/PluginManager.kt @@ -14,10 +14,8 @@ package net.mamoe.mirai.console.plugin import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl import net.mamoe.mirai.console.plugin.description.PluginDescription -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import java.io.File import java.nio.file.Path -import java.util.* /** * 插件管理器. @@ -103,22 +101,6 @@ public interface PluginManager { */ public val pluginLoaders: List> - /** - * 手动注册一个扩展的插件加载器. 在启动时会通过 [ServiceLoader] 加载, 但也可以手动注册. - * - * @see PluginLoader 插件加载器 - */ - @ConsoleExperimentalAPI - public fun PluginLoader<*, *>.register(): Boolean - - /** - * 取消注册一个扩展的插件加载器 - * - * @see PluginLoader 插件加载器 - */ - @ConsoleExperimentalAPI - public fun PluginLoader<*, *>.unregister(): Boolean - /** * 获取插件的 [描述][PluginDescription], 通过 [PluginLoader.getDescription] */ @@ -158,8 +140,6 @@ public interface PluginManager { public companion object INSTANCE : PluginManager by PluginManagerImpl { // due to Kotlin's bug public override val Plugin.description: PluginDescription get() = PluginManagerImpl.run { description } - public override fun PluginLoader<*, *>.register(): Boolean = PluginManagerImpl.run { register() } - public override fun PluginLoader<*, *>.unregister(): Boolean = PluginManagerImpl.run { unregister() } public override fun Plugin.disable(): Unit = PluginManagerImpl.run { disable() } public override fun Plugin.enable(): Unit = PluginManagerImpl.run { enable() } public override fun Plugin.load(): Unit = PluginManagerImpl.run { load() } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginDescription.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginDescription.kt index c11f4d565..301c04b97 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginDescription.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginDescription.kt @@ -20,13 +20,6 @@ import net.mamoe.mirai.console.plugin.PluginLoadException * @see Plugin */ public interface PluginDescription { - /** - * 插件类型. 将会决定加载顺序 - * - * @see PluginLoadPriority - */ - public val loadPriority: PluginLoadPriority - /** * 插件 ID, 必须全英文, 仅允许英文字母, '-', '_', '.'. * diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginLoadPriority.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginLoadPriority.kt deleted file mode 100644 index 8f49d63e8..000000000 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/description/PluginLoadPriority.kt +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.console.plugin.description - -import kotlinx.serialization.KSerializer -import kotlinx.serialization.builtins.serializer -import net.mamoe.mirai.console.extension.Extension -import net.mamoe.mirai.console.extensions.BotConfigurationAlterer -import net.mamoe.mirai.console.extensions.PermissionServiceProvider -import net.mamoe.mirai.console.extensions.PluginLoaderProvider -import net.mamoe.mirai.console.extensions.SingletonExtensionSelector -import net.mamoe.mirai.console.internal.data.map -import net.mamoe.mirai.console.plugin.description.PluginLoadPriority.* - -/** - * 插件类型. - * - * 插件类型将影响加载顺序: [BEFORE_EXTENSIONS] -> [ON_EXTENSIONS] -> [AFTER_EXTENSIONS]. - * - * 依赖解决过程与插件类型有很大关联. 在一个较早的阶段, 只会解决在此阶段加载的插件. 意味着 [BEFORE_EXTENSIONS] 不允许依赖一个 [AFTER_EXTENSIONS] 类型的插件. - */ -public enum class PluginLoadPriority { - /** - * 表示此插件最早被加载. 在 Console 启动时的第一初始化阶段就会加载这些插件. - * - * 一般只有提供 [PluginLoaderProvider] 或 [SingletonExtensionSelector] 的插件才需要在此阶段加载. - */ - BEFORE_EXTENSIONS, - - /** - * 表示此插件提供一些高优先级的 [Extension], 应在加载其他 [AFTER_EXTENSIONS] 类型插件前加载 - * - * 高优先级的 [Extension] 通常是覆盖 Console 内置的部分服务的扩展. 如 [PermissionServiceProvider]. - * - * 一些普通的 [Extension], 如 [BotConfigurationAlterer], 也可以使用 [AFTER_EXTENSIONS] 类型插件注册. - */ - ON_EXTENSIONS, - - /** - * 表示此插件为一个通常的插件, 在扩展处理完毕后加载. - */ - AFTER_EXTENSIONS; - - public object AsStringSerializer : KSerializer by String.serializer().map( - serializer = { it.name }, - deserializer = { str -> - values().firstOrNull { - it.name.equals(str, ignoreCase = true) - } ?: AFTER_EXTENSIONS - } - ) -} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt index 3d3c51659..2fd32ea9f 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt @@ -7,10 +7,13 @@ * 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 +import net.mamoe.mirai.console.data.AutoSavePluginDataHolder +import net.mamoe.mirai.console.data.PluginConfig +import net.mamoe.mirai.console.data.PluginData import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal import net.mamoe.mirai.console.util.ConsoleExperimentalAPI import net.mamoe.mirai.utils.minutesToMillis @@ -19,18 +22,52 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext /** - * [JavaPlugin] 和 [KotlinPlugin] 的父类 + * [JavaPlugin] 和 [KotlinPlugin] 的父类. 所有 [JvmPlugin] 都应该拥有此类作为直接或间接父类. * * @see JavaPlugin * @see KotlinPlugin */ public abstract class AbstractJvmPlugin @JvmOverloads constructor( - parentCoroutineContext: CoroutineContext = EmptyCoroutineContext -) : JvmPlugin, JvmPluginInternal(parentCoroutineContext) { + parentCoroutineContext: CoroutineContext = EmptyCoroutineContext, +) : JvmPlugin, JvmPluginInternal(parentCoroutineContext), AutoSavePluginDataHolder { @ConsoleExperimentalAPI public final override val dataHolderName: String get() = this.description.name + public final override val loader: JarPluginLoader get() = super.loader + + /** + * 重载 [PluginData] + * + * @see reloadPluginData + */ + @JvmName("reloadPluginData") + public fun T.reload(): Unit = loader.dataStorage.load(this@AbstractJvmPlugin, this) + + /** + * 重载 [PluginConfig] + * + * @see reloadPluginConfig + */ + @JvmName("reloadPluginConfig") + public fun T.reload(): Unit = loader.configStorage.load(this@AbstractJvmPlugin, this) + @ConsoleExperimentalAPI public override val autoSaveIntervalMillis: LongRange = 30.secondsToMillis..10.minutesToMillis -} \ No newline at end of file +} + +/** + * 重载一个 [PluginData] + * + * @see AbstractJvmPlugin.reload + */ +@JvmSynthetic +public inline fun AbstractJvmPlugin.reloadPluginData(instance: PluginData): Unit = this.run { instance.reload() } + +/** + * 重载一个 [PluginConfig] + * + * @see AbstractJvmPlugin.reload + */ +@JvmSynthetic +public inline fun AbstractJvmPlugin.reloadPluginConfig(instance: PluginConfig): Unit = this.run { instance.reload() } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt index b6ce680a7..bfb986340 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt @@ -18,23 +18,18 @@ package net.mamoe.mirai.console.plugin.jvm import kotlinx.coroutines.CoroutineScope -import net.mamoe.mirai.console.data.AutoSavePluginDataHolder -import net.mamoe.mirai.console.data.PluginConfig -import net.mamoe.mirai.console.data.PluginData +import net.mamoe.mirai.console.extension.ScopedComponentStorage import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionIdNamespace import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.PluginFileExtensions import net.mamoe.mirai.console.plugin.ResourceContainer -import net.mamoe.mirai.console.plugin.getDescription import net.mamoe.mirai.utils.MiraiLogger /** * Java, Kotlin 或其他 JVM 平台插件 * - * 有关 [JvmPlugin] 相关实现方法,请参考 - * * @see AbstractJvmPlugin 默认实现 * * @see JavaPlugin Java 插件 @@ -45,71 +40,39 @@ import net.mamoe.mirai.utils.MiraiLogger */ @OptIn(ExperimentalPermission::class) public interface JvmPlugin : Plugin, CoroutineScope, - PluginFileExtensions, ResourceContainer, AutoSavePluginDataHolder, PermissionIdNamespace { + PluginFileExtensions, ResourceContainer, PermissionIdNamespace { /** 日志 */ public val logger: MiraiLogger /** 插件描述 */ - public val description: JvmPluginDescription get() = loader.getDescription(this) + public val description: JvmPluginDescription /** 所属插件加载器实例 */ - @JvmDefault - public override val loader: JarPluginLoader - get() = JarPluginLoader - - /** - * 重载 [PluginData] - * - * @see reloadPluginData - */ - @JvmDefault - @JvmName("reloadPluginData") - public fun T.reload(): Unit = loader.dataStorage.load(this@JvmPlugin, this) - - /** - * 重载 [PluginConfig] - * - * @see reloadPluginConfig - */ - @JvmDefault - @JvmName("reloadPluginConfig") - public fun T.reload(): Unit = loader.configStorage.load(this@JvmPlugin, this) + // `final` in AbstractJvmPlugin + public override val loader: JarPluginLoader get() = JarPluginLoader /** * 在插件被加载时调用. 只会被调用一次. + * + * 在 [onLoad] 时可注册扩展 [ScopedComponentStorage.contribute] + * + * @receiver 组件容器 */ - @JvmDefault - public fun onLoad() { - } + public fun @ParameterName("storage") ScopedComponentStorage.onLoad() {} /** * 在插件被启用时调用, 可能会被调用多次 */ - @JvmDefault - public fun onEnable() { - } + public fun onEnable() {} /** * 在插件被关闭时调用, 可能会被调用多次 */ - @JvmDefault - public fun onDisable() { + public fun onDisable() {} + + public companion object { + @JvmSynthetic + public inline fun JvmPlugin.onLoad(storage: ScopedComponentStorage): Unit = storage.onLoad() } -} - -/** - * 重载一个 [PluginData] - * - * @see JvmPlugin.reload - */ -@JvmSynthetic -public inline fun JvmPlugin.reloadPluginData(instance: PluginData): Unit = this.run { instance.reload() } - -/** - * 重载一个 [PluginConfig] - * - * @see JvmPlugin.reload - */ -@JvmSynthetic -public inline fun JvmPlugin.reloadPluginConfig(instance: PluginConfig): Unit = this.run { instance.reload() } \ No newline at end of file +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt index 64be7d2a9..30f366424 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPluginDescription.kt @@ -14,7 +14,6 @@ package net.mamoe.mirai.console.plugin.jvm import com.vdurmont.semver4j.Semver import net.mamoe.mirai.console.plugin.description.PluginDependency import net.mamoe.mirai.console.plugin.description.PluginDescription -import net.mamoe.mirai.console.plugin.description.PluginLoadPriority import kotlin.internal.LowPriorityInOverloadResolution /** @@ -22,6 +21,8 @@ import kotlin.internal.LowPriorityInOverloadResolution * * 请不要自行实现 [JvmPluginDescription] 接口. 它不具有继承稳定性. * + * 要查看相关约束, 参考 [PluginDescription] + * * @see SimpleJvmPluginDescription * @see JvmPluginDescriptionBuilder */ @@ -82,7 +83,6 @@ public class JvmPluginDescriptionBuilder( private var author: String = "" private var info: String = "" private var dependencies: MutableSet = mutableSetOf() - private var loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS @ILoveKuriyamaMiraiForever public fun name(value: String): JvmPluginDescriptionBuilder = apply { this.name = value.trim() } @@ -103,21 +103,6 @@ public class JvmPluginDescriptionBuilder( @ILoveKuriyamaMiraiForever public fun info(value: String): JvmPluginDescriptionBuilder = apply { this.info = value.trimIndent() } - @ILoveKuriyamaMiraiForever - public fun kind(value: PluginLoadPriority): JvmPluginDescriptionBuilder = apply { this.loadPriority = value } - - @ILoveKuriyamaMiraiForever - public fun normalPlugin(): JvmPluginDescriptionBuilder = - apply { this.loadPriority = PluginLoadPriority.AFTER_EXTENSIONS } - - @ILoveKuriyamaMiraiForever - public fun loaderProviderPlugin(): JvmPluginDescriptionBuilder = - apply { this.loadPriority = PluginLoadPriority.BEFORE_EXTENSIONS } - - @ILoveKuriyamaMiraiForever - public fun highPriorityExtensionsPlugin(): JvmPluginDescriptionBuilder = - apply { this.loadPriority = PluginLoadPriority.ON_EXTENSIONS } - @ILoveKuriyamaMiraiForever public fun dependsOn( pluginId: String, @@ -154,7 +139,7 @@ public class JvmPluginDescriptionBuilder( @Suppress("DEPRECATION_ERROR") public fun build(): JvmPluginDescription = - SimpleJvmPluginDescription(name, version, id, author, info, dependencies, loadPriority) + SimpleJvmPluginDescription(name, version, id, author, info, dependencies) @Retention(AnnotationRetention.SOURCE) @DslMarker @@ -194,7 +179,6 @@ public data class SimpleJvmPluginDescription public override val author: String = "", public override val info: String = "", public override val dependencies: Set = setOf(), - public override val loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS, ) : JvmPluginDescription { @Deprecated( @@ -216,8 +200,7 @@ public data class SimpleJvmPluginDescription author: String = "", info: String = "", dependencies: Set = setOf(), - loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS, - ) : this(name, Semver(version, Semver.SemverType.LOOSE), id, author, info, dependencies, loadPriority) + ) : this(name, Semver(version, Semver.SemverType.LOOSE), id, author, info, dependencies) init { require(!name.contains(':')) { "':' is forbidden in plugin name" } @@ -242,8 +225,7 @@ public fun JvmPluginDescription( author: String = "", info: String = "", dependencies: Set = setOf(), - loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS -): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, loadPriority) +): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies) @Deprecated( "JvmPluginDescription 没有构造器. 请使用 SimpleJvmPluginDescription.", @@ -262,5 +244,4 @@ public fun JvmPluginDescription( author: String = "", info: String = "", dependencies: Set = setOf(), - loadPriority: PluginLoadPriority = PluginLoadPriority.AFTER_EXTENSIONS -): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, loadPriority) +): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies) From 2223451b7089051bfce20b29a0efc4a099f4690c Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 11 Sep 2020 23:08:15 +0800 Subject: [PATCH 02/14] Ignore blank inputs --- .../main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt index 80751f6cd..dd1bd9133 100644 --- a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt @@ -34,6 +34,7 @@ internal fun startupConsoleThread() { try { val next = MiraiConsole.requestInput("").let { when { + it.isBlank() -> it it.startsWith(CommandManager.commandPrefix) -> it it == "?" -> CommandManager.commandPrefix + BuiltInCommands.HelpCommand.primaryName else -> CommandManager.commandPrefix + it From e41a2c0d09f906b2af6a548418600c4a7097cc94 Mon Sep 17 00:00:00 2001 From: Him188 Date: Fri, 11 Sep 2020 23:22:43 +0800 Subject: [PATCH 03/14] Fix CombinedScope --- .../kotlin/net/mamoe/mirai/console/util/MessageScope.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt index eb95259d4..91309fbba 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt @@ -526,8 +526,8 @@ internal fun MessageScope.asSequence(): Sequence { } private class CombinedScope( - private val first: MessageScope, - private val second: MessageScope + val first: MessageScope, + val second: MessageScope, ) : MessageScope { override val realTarget: Any? get() = null @@ -549,7 +549,7 @@ private class CombinedScope( } private class CommandSenderAsMessageScope( - private val sender: CommandSender + private val sender: CommandSender, ) : MessageScope { override val realTarget: Any? get() = sender.user ?: sender // ConsoleCommandSender @@ -564,7 +564,7 @@ private class CommandSenderAsMessageScope( } private class ContactAsMessageScope( - private val sender: Contact + private val sender: Contact, ) : MessageScope { override val realTarget: Any? get() = sender From 956e193d020d50c34c4fd682ec3be16d642f1fb9 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 13:31:34 +0800 Subject: [PATCH 04/14] Correct class naming following Kotlin formal style --- .../net/mamoe/mirai/console/MiraiConsole.kt | 16 ++++----- .../mirai/console/command/BuiltInCommands.kt | 10 +++--- .../mirai/console/command/CommandSender.kt | 8 ++--- .../mirai/console/command/CompositeCommand.kt | 4 +-- .../description/CommandArgumentContext.kt | 6 ++-- .../console/command/java/JCompositeCommand.kt | 4 +-- .../mirai/console/data/AutoSavePluginData.kt | 6 ++-- .../console/data/AutoSavePluginDataHolder.kt | 6 ++-- .../mamoe/mirai/console/data/PluginData.kt | 11 +++--- .../console/data/PluginDataExtensions.kt | 4 +-- .../mirai/console/data/PluginDataHolder.kt | 6 ++-- .../mirai/console/data/PluginDataStorage.kt | 12 +++---- .../net/mamoe/mirai/console/data/Value.kt | 34 +++++++++---------- .../mirai/console/extension/Extension.kt | 10 +++--- .../mirai/console/extension/ExtensionPoint.kt | 14 ++++---- .../extensions/SingletonExtensionSelector.kt | 4 +-- .../MiraiConsoleImplementationBridge.kt | 6 ++-- .../data/MultiFilePluginDataStorageImpl.kt | 4 +-- .../permission/PermissibleIdentifier.kt | 4 +-- .../mirai/console/permission/Permission.kt | 4 +-- .../console/plugin/center/PluginCenter.kt | 8 ++--- .../console/plugin/jvm/AbstractJvmPlugin.kt | 6 ++-- .../console/plugin/jvm/JarPluginLoader.kt | 8 ++--- .../mamoe/mirai/console/util/Annotations.kt | 10 +++--- .../mamoe/mirai/console/util/ContactUtils.kt | 10 +++--- .../mirai/console/util/CoroutineScopeUtils.kt | 10 +++--- .../mamoe/mirai/console/util/MessageScope.kt | 2 +- .../mamoe/mirai/console/TestMiraiConosle.kt | 8 ++--- .../mamoe/mirai/console/data/SettingTest.kt | 4 +-- buildSrc/src/main/kotlin/Versions.kt | 2 +- .../mamoe/mirai/console/pure/ConsoleThread.kt | 4 +-- .../pure/MiraiConsoleImplementationPure.kt | 8 ++--- .../console/pure/MiraiConsolePureLoader.kt | 12 +++---- 33 files changed, 132 insertions(+), 133 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt index e82df754f..87cd2f6c8 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsole.kt @@ -8,7 +8,7 @@ */ @file:Suppress("WRONG_MODIFIER_CONTAINING_DECLARATION", "unused") -@file:OptIn(ConsoleInternalAPI::class) +@file:OptIn(ConsoleInternalApi::class) package net.mamoe.mirai.console @@ -25,8 +25,8 @@ import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.center.PluginCenter import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI -import net.mamoe.mirai.console.util.ConsoleInternalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi +import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.MiraiLogger @@ -60,7 +60,7 @@ public interface MiraiConsole : CoroutineScope { * * **注意**: 插件不应该在任何时刻使用它. */ - @ConsoleInternalAPI + @ConsoleInternalApi public val mainLogger: MiraiLogger /** @@ -80,13 +80,13 @@ public interface MiraiConsole : CoroutineScope { */ public val version: Semver - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public val pluginCenter: PluginCenter /** * 创建一个 logger */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun createLogger(identity: String?): MiraiLogger public companion object INSTANCE : MiraiConsole by MiraiConsoleImplementationBridge { @@ -106,7 +106,7 @@ public interface MiraiConsole : CoroutineScope { * @see BotConfigurationAlterer ExtensionPoint */ // don't static - @ConsoleExperimentalAPI("This is a low-level API and might be removed in the future.") + @ConsoleExperimentalApi("This is a low-level API and might be removed in the future.") public fun addBot(id: Long, password: String, configuration: BotConfiguration.() -> Unit = {}): Bot = addBotImpl(id, password, configuration) @@ -118,7 +118,7 @@ public interface MiraiConsole : CoroutineScope { * @see Bot.botInstances 获取现有 [Bot] 实例列表 * @see BotConfigurationAlterer ExtensionPoint */ - @ConsoleExperimentalAPI("This is a low-level API and might be removed in the future.") + @ConsoleExperimentalApi("This is a low-level API and might be removed in the future.") public fun addBot(id: Long, password: ByteArray, configuration: BotConfiguration.() -> Unit = {}): Bot = addBotImpl(id, password, configuration) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt index 770b9dbb3..ad390ef01 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt @@ -25,8 +25,8 @@ import net.mamoe.mirai.console.permission.PermissionService.Companion.denyPermis import net.mamoe.mirai.console.permission.PermissionService.Companion.findCorrespondingPermissionOrFail import net.mamoe.mirai.console.permission.PermissionService.Companion.getGrantedPermissions import net.mamoe.mirai.console.permission.PermissionService.Companion.grantPermission -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI -import net.mamoe.mirai.console.util.ConsoleInternalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi +import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.contact.* import net.mamoe.mirai.event.events.EventCancelledException import net.mamoe.mirai.message.nextMessageOrNull @@ -35,7 +35,7 @@ import kotlin.concurrent.thread import kotlin.system.exitProcess -@ConsoleExperimentalAPI +@ConsoleExperimentalApi @Suppress("EXPOSED_SUPER_INTERFACE") public interface BuiltInCommand : Command, BuiltInCommandInternal @@ -45,7 +45,7 @@ internal interface BuiltInCommandInternal : Command /** * 内建指令列表 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi @Suppress("unused") @OptIn(ExperimentalPermission::class) public object BuiltInCommands { @@ -101,7 +101,7 @@ public object BuiltInCommands { }, onFailure = { if (it is CancellationException) return@fold - @OptIn(ConsoleInternalAPI::class) + @OptIn(ConsoleInternalApi::class) MiraiConsole.mainLogger.error("Exception in stop", it) ignoreException { sendMessage( diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt index af199bcb4..1aa13de3d 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt @@ -36,7 +36,7 @@ import net.mamoe.mirai.console.permission.AbstractPermissibleIdentifier import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permissible import net.mamoe.mirai.console.permission.PermissibleIdentifier -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext import net.mamoe.mirai.console.util.MessageScope @@ -180,7 +180,7 @@ public interface CommandSender : CoroutineScope, Permissible { @JvmBlockingBridge public suspend fun sendMessage(message: String): MessageReceipt? - @ConsoleExperimentalAPI("This is unstable and might get changed") + @ConsoleExperimentalApi("This is unstable and might get changed") public suspend fun catchExecutionException(e: Throwable) public companion object { @@ -282,7 +282,7 @@ public sealed class AbstractCommandSender : CommandSender, CoroutineScope { public abstract override val user: User? public abstract override fun toString(): String - @ConsoleExperimentalAPI("This is unstable and might get changed") + @ConsoleExperimentalApi("This is unstable and might get changed") override suspend fun catchExecutionException(e: Throwable) { if (this is CommandSenderOnMessage<*>) { val cause = e.rootCauseOrSelf @@ -469,7 +469,7 @@ public inline fun CommandSender.fold( * @return [inGroup] 或 [inPrivate] 执行结果. */ @JvmSynthetic -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public inline fun UserCommandSender.foldContext( inGroup: MemberCommandSender.() -> R, inPrivate: UserCommandSender.() -> R, diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt index 7cea5b132..bf3fe97f5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt @@ -22,7 +22,7 @@ import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand import net.mamoe.mirai.console.internal.command.CompositeCommandSubCommandAnnotationResolver import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.message.data.MessageChain import kotlin.annotation.AnnotationRetention.RUNTIME import kotlin.annotation.AnnotationTarget.FUNCTION @@ -81,7 +81,7 @@ import kotlin.annotation.AnnotationTarget.FUNCTION * * @see buildCommandArgumentContext */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public abstract class CompositeCommand @OptIn(ExperimentalPermission::class) constructor( owner: CommandOwner, vararg names: String, diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt index f02c4e39d..e071fd0ff 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt @@ -16,7 +16,7 @@ import net.mamoe.mirai.console.command.CommandSender import net.mamoe.mirai.console.command.CompositeCommand import net.mamoe.mirai.console.command.SimpleCommand import net.mamoe.mirai.console.command.description.CommandArgumentContext.ParserPair -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.contact.* import kotlin.internal.LowPriorityInOverloadResolution import kotlin.reflect.KClass @@ -238,7 +238,7 @@ public class CommandArgumentContextBuilder : MutableList> by mutab /** * 添加一个指令解析器 */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi @JvmSynthetic public inline infix fun add( crossinline parser: CommandArgumentParser<*>.(s: String) -> T @@ -249,7 +249,7 @@ public class CommandArgumentContextBuilder : MutableList> by mutab /** * 添加一个指令解析器 */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi @JvmSynthetic @LowPriorityInOverloadResolution public inline infix fun add( diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt index 6ce98456a..2c62b5959 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt @@ -16,7 +16,7 @@ import net.mamoe.mirai.console.command.CompositeCommand import net.mamoe.mirai.console.command.description.buildCommandArgumentContext import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** * 复合指令. 指令注册时候会通过反射构造指令解析器. @@ -68,7 +68,7 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalAPI * * @see buildCommandArgumentContext */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public abstract class JCompositeCommand @OptIn(ExperimentalPermission::class) @JvmOverloads constructor( owner: CommandOwner, diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt index 662242882..85e45bc10 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginData.kt @@ -16,7 +16,7 @@ import kotlinx.coroutines.* import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip import net.mamoe.mirai.console.internal.plugin.updateWhen -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.utils.* /** @@ -38,7 +38,7 @@ public open class AutoSavePluginData private constructor( public constructor() : this(null) - @ConsoleExperimentalAPI + @ConsoleExperimentalApi override fun onInit(owner: PluginDataHolder, storage: PluginDataStorage) { check(owner is AutoSavePluginDataHolder) { "owner must be AutoSavePluginDataHolder for AutoSavePluginData" } @@ -89,7 +89,7 @@ public open class AutoSavePluginData private constructor( /** * @return `true` 时, 一段时间后, 即使无属性改变, 也会进行保存. */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi protected open fun shouldPerformAutoSaveWheneverChanged(): Boolean { return true } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginDataHolder.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginDataHolder.kt index 5b4265865..2237e1ec7 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginDataHolder.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/AutoSavePluginDataHolder.kt @@ -3,7 +3,7 @@ package net.mamoe.mirai.console.data import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** * 可以持有相关 [AutoSavePluginData] 的对象. @@ -13,7 +13,7 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalAPI * * @see net.mamoe.mirai.console.plugin.jvm.JvmPlugin */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface AutoSavePluginDataHolder : PluginDataHolder, CoroutineScope { /** * [AutoSavePluginData] 每次自动保存时间间隔 @@ -27,6 +27,6 @@ public interface AutoSavePluginDataHolder : PluginDataHolder, CoroutineScope { * @see LongRange Java 用户使用 [LongRange] 的构造器创建 * @see Long.rangeTo Kotlin 用户使用 [Long.rangeTo] 创建, 如 `3000..50000` */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public val autoSaveIntervalMillis: LongRange } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt index 08f44ceb3..d4004c82f 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginData.kt @@ -21,8 +21,7 @@ import kotlinx.serialization.KSerializer import net.mamoe.mirai.console.data.java.JAutoSavePluginData import net.mamoe.mirai.console.internal.data.* import net.mamoe.mirai.console.plugin.jvm.JvmPlugin -import net.mamoe.mirai.console.plugin.jvm.reloadPluginData -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import kotlin.internal.LowPriorityInOverloadResolution import kotlin.reflect.KClass import kotlin.reflect.KProperty @@ -117,7 +116,7 @@ public interface PluginData { /** * 这个 [PluginData] 保存时使用的名称. 默认通过 [ValueName] 获取, 否则使用 [类全名][KClass.qualifiedName] (即 [Class.getCanonicalName]) */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public val saveName: String get() { val clazz = this::class @@ -129,7 +128,7 @@ public interface PluginData { /** * 由 [provideDelegate] 创建, 来自一个通过 `by value` 初始化的属性节点. */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public data class ValueNode( /** * 节点名称. @@ -191,7 +190,7 @@ public interface PluginData { /** * 当这个 [PluginData] 被放入一个 [PluginDataStorage] 时调用 */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun onInit(owner: PluginDataHolder, storage: PluginDataStorage) } @@ -346,6 +345,6 @@ internal fun PluginData.valueImpl(type: KType, classifier: KClass<*>): Seria * - 使用 [kotlinx.serialization](https://github.com/Kotlin/kotlinx.serialization) 的 [Serializable] 标记的类 */ @Suppress("UNCHECKED_CAST") -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public fun PluginData.valueFromKType(type: KType, default: T): SerializerAwareValue = (valueFromKTypeImpl(type) as SerializerAwareValue).apply { this.value = default } as SerializerAwareValue diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataExtensions.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataExtensions.kt index 3a610c6f5..654687d49 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataExtensions.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataExtensions.kt @@ -4,7 +4,7 @@ package net.mamoe.mirai.console.data import net.mamoe.mirai.console.data.PluginDataExtensions.withDefault import net.mamoe.mirai.console.internal.data.ShadowMap -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import kotlin.internal.LowPriorityInOverloadResolution /** @@ -12,7 +12,7 @@ import kotlin.internal.LowPriorityInOverloadResolution */ public object PluginDataExtensions { - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public open class NotNullMap internal constructor( private val delegate: Map ) : Map by delegate { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataHolder.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataHolder.kt index 2c89f3587..06d655913 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataHolder.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataHolder.kt @@ -11,7 +11,7 @@ package net.mamoe.mirai.console.data -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** * 可以持有相关 [PluginData] 实例的对象, 作为 [PluginData] 实例的拥有者. @@ -21,12 +21,12 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalAPI * * @see AutoSavePluginDataHolder 支持自动保存 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PluginDataHolder { /** * 保存时使用的分类名 */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public val dataHolderName: String } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt index 112ceebda..05c10facf 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/PluginDataStorage.kt @@ -15,7 +15,7 @@ import net.mamoe.mirai.console.internal.data.MemoryPluginDataStorageImpl import net.mamoe.mirai.console.internal.data.MultiFilePluginDataStorageImpl import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import net.mamoe.mirai.console.plugin.jvm.JvmPlugin -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import java.io.File import java.nio.file.Path @@ -33,12 +33,12 @@ import java.nio.file.Path * @see PluginDataHolder * @see JarPluginLoader.dataStorage */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PluginDataStorage { /** * 读取一个实例. 并为 [instance] [设置 [PluginDataStorage]][PluginData.onInit] */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun load(holder: PluginDataHolder, instance: PluginData) /** @@ -46,7 +46,7 @@ public interface PluginDataStorage { * * **实现细节**: 调用 [PluginData.updaterSerializer] */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun store(holder: PluginDataHolder, instance: PluginData) /* @@ -96,7 +96,7 @@ public companion object { * 在内存存储所有 [PluginData] 实例的 [PluginDataStorage]. 在内存数据丢失后相关 [PluginData] 实例也会丢失. * @see PluginDataStorage */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface MemoryPluginDataStorage : PluginDataStorage { public companion object { /** @@ -112,7 +112,7 @@ public interface MemoryPluginDataStorage : PluginDataStorage { /** * 用多个文件存储 [PluginData] 实例的 [PluginDataStorage]. */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface MultiFilePluginDataStorage : PluginDataStorage { /** * 存放 [PluginData] 的目录. diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/Value.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/Value.kt index 95ff1850a..14bc75e65 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/Value.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/data/Value.kt @@ -16,7 +16,7 @@ import kotlinx.serialization.KSerializer import kotlinx.serialization.StringFormat import net.mamoe.mirai.console.internal.data.map import net.mamoe.mirai.console.internal.data.setValueBySerializer -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -212,7 +212,7 @@ public interface StringValue : PrimitiveValue /** * 复合数据类型实现 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface CompositeValue : Value @@ -227,7 +227,7 @@ public interface ListValue : CompositeValue> * * @param E 不是基础数据类型 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface CompositeListValue : ListValue /** @@ -235,16 +235,16 @@ public interface CompositeListValue : ListValue * * @param E 是基础类型 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveListValue : ListValue //// region PrimitiveListValue CODEGEN //// -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveIntListValue : PrimitiveListValue -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveLongListValue : PrimitiveListValue // TODO + codegen @@ -255,30 +255,30 @@ public interface PrimitiveLongListValue : PrimitiveListValue * @see [CompositeSetValue] * @see [PrimitiveSetValue] */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface SetValue : CompositeValue> /** * 复合数据类型 [Set] * @param E 是基础数据类型 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface CompositeSetValue : SetValue /** * 基础数据类型 [Set] * @param E 是基础数据类型 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveSetValue : SetValue //// region PrimitiveSetValue CODEGEN //// -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveIntSetValue : PrimitiveSetValue -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveLongSetValue : PrimitiveSetValue // TODO + codegen @@ -289,27 +289,27 @@ public interface PrimitiveLongSetValue : PrimitiveSetValue * @see [CompositeMapValue] * @see [PrimitiveMapValue] */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface MapValue : CompositeValue> -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface CompositeMapValue : MapValue -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveMapValue : MapValue //// region PrimitiveMapValue CODEGEN //// -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveIntIntMapValue : PrimitiveMapValue -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PrimitiveIntLongMapValue : PrimitiveMapValue // TODO + codegen //// endregion PrimitiveSetValue CODEGEN //// -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface ReferenceValue : Value \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt index 62705a203..7cf54a405 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/Extension.kt @@ -13,18 +13,18 @@ import net.mamoe.mirai.console.extensions.PermissionServiceProvider import net.mamoe.mirai.console.extensions.PluginLoaderProvider import net.mamoe.mirai.console.extensions.SingletonExtensionSelector import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** * 表示一个扩展. */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface Extension /** * 增加一些函数 (方法)的扩展 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface FunctionExtension : Extension /** @@ -34,7 +34,7 @@ public interface FunctionExtension : Extension * * @see PermissionServiceProvider */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface SingletonExtension : Extension { public val instance: T } @@ -44,7 +44,7 @@ public interface SingletonExtension : Extension { * * @see PluginLoaderProvider */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface InstanceExtension : Extension { public val instance: T } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt index 8a35055bb..6fda56d81 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ExtensionPoint.kt @@ -12,18 +12,18 @@ package net.mamoe.mirai.console.extension import net.mamoe.mirai.console.plugin.PluginLoader -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import kotlin.reflect.KClass import kotlin.reflect.full.isSubclassOf -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface ExtensionPoint { public val type: KClass public companion object { @JvmStatic @JvmSynthetic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public inline fun ExtensionPoint<*>.isFor(exactType: Boolean = false): Boolean { return if (exactType) { T::class == type @@ -32,15 +32,15 @@ public interface ExtensionPoint { } } -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface SingletonExtensionPoint> : ExtensionPoint /** * 表示一个扩展点 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public open class AbstractExtensionPoint( - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public override val type: KClass, ) : ExtensionPoint @@ -53,7 +53,7 @@ public open class AbstractExtensionPoint( * @see PluginLoader.disable * @see PluginLoader.description */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public open class ExtensionException : RuntimeException { public constructor() : super() public constructor(message: String?) : super(message) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt index 49adf4239..da4bb2261 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/SingletonExtensionSelector.kt @@ -14,7 +14,7 @@ import net.mamoe.mirai.console.extension.* import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.name -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.utils.info import kotlin.reflect.KClass @@ -23,7 +23,7 @@ import kotlin.reflect.KClass * * 如有多个 [SingletonExtensionSelector] 注册, 将会停止服务器. */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface SingletonExtensionSelector : FunctionExtension { public data class Registry( val plugin: Plugin, diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt index a15c3955c..7109b7c0e 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt @@ -7,7 +7,7 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -@file:OptIn(ConsoleExperimentalAPI::class) +@file:OptIn(ConsoleExperimentalApi::class) package net.mamoe.mirai.console.internal @@ -47,7 +47,7 @@ import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.PluginManager import net.mamoe.mirai.console.plugin.center.PluginCenter import net.mamoe.mirai.console.plugin.jvm.AbstractJvmPlugin -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleInput import net.mamoe.mirai.utils.* import java.nio.file.Path @@ -93,7 +93,7 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI override fun createLogger(identity: String?): MiraiLogger = instance.createLogger(identity) - @OptIn(ConsoleExperimentalAPI::class, ExperimentalPermission::class) + @OptIn(ConsoleExperimentalApi::class, ExperimentalPermission::class) @Suppress("RemoveRedundantBackticks") internal fun doStart() { phase `greeting`@{ diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt index bfb93c4c5..8b8abc116 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt @@ -15,7 +15,7 @@ import net.mamoe.mirai.console.data.PluginDataHolder import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip import net.mamoe.mirai.console.permission.ExperimentalPermission -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.SilentLogger import net.mamoe.mirai.utils.debug @@ -63,7 +63,7 @@ internal open class MultiFilePluginDataStorageImpl( return file.toFile().also { it.createNewFile() } } - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public override fun store(holder: PluginDataHolder, instance: PluginData) { @OptIn(ExperimentalPermission::class) val yaml =/* if (instance.saveName == "PermissionService") Json { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt index 695b8cc97..6db38f796 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt @@ -15,7 +15,7 @@ import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable import kotlinx.serialization.builtins.serializer import net.mamoe.mirai.console.internal.data.map -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** */ @@ -109,7 +109,7 @@ public sealed class AbstractPermissibleIdentifier( } } - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public object AsStringSerializer : KSerializer by String.serializer().map( serializer = { it.toString() }, diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt index 78cb76515..e251b77de 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt @@ -9,7 +9,7 @@ package net.mamoe.mirai.console.permission -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** @@ -49,7 +49,7 @@ public val RootConsoleBuiltInPermission: Permission by lazy { ) } -@ConsoleExperimentalAPI +@ConsoleExperimentalApi @ExperimentalPermission public fun Permission.parentsWithSelfSequence(): Sequence = generateSequence(this) { p -> diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt index 30ac29a0c..0f1791400 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/center/PluginCenter.kt @@ -11,14 +11,14 @@ package net.mamoe.mirai.console.plugin.center import kotlinx.serialization.SerialName import kotlinx.serialization.Serializable -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import java.io.File -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public interface PluginCenter { @Serializable - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public data class PluginInsight( val name: String, val version: String, @@ -32,7 +32,7 @@ public interface PluginCenter { val commands: List ) - @ConsoleExperimentalAPI + @ConsoleExperimentalApi @Serializable public data class PluginInfo( val name: String, diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt index 2fd32ea9f..23e63ab7a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt @@ -15,7 +15,7 @@ import net.mamoe.mirai.console.data.AutoSavePluginDataHolder import net.mamoe.mirai.console.data.PluginConfig import net.mamoe.mirai.console.data.PluginData import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.utils.minutesToMillis import net.mamoe.mirai.utils.secondsToMillis import kotlin.coroutines.CoroutineContext @@ -30,7 +30,7 @@ import kotlin.coroutines.EmptyCoroutineContext public abstract class AbstractJvmPlugin @JvmOverloads constructor( parentCoroutineContext: CoroutineContext = EmptyCoroutineContext, ) : JvmPlugin, JvmPluginInternal(parentCoroutineContext), AutoSavePluginDataHolder { - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public final override val dataHolderName: String get() = this.description.name @@ -52,7 +52,7 @@ public abstract class AbstractJvmPlugin @JvmOverloads constructor( @JvmName("reloadPluginConfig") public fun T.reload(): Unit = loader.configStorage.load(this@AbstractJvmPlugin, this) - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public override val autoSaveIntervalMillis: LongRange = 30.secondsToMillis..10.minutesToMillis } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt index 35b83b8fe..160dbf5cc 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JarPluginLoader.kt @@ -13,23 +13,23 @@ import kotlinx.coroutines.CoroutineScope import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.internal.plugin.JarPluginLoaderImpl import net.mamoe.mirai.console.plugin.FilePluginLoader -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** * 内建的 Jar (JVM) 插件加载器 */ -@ConsoleExperimentalAPI("classname might change") +@ConsoleExperimentalApi("classname might change") public interface JarPluginLoader : CoroutineScope, FilePluginLoader { /** * [JvmPlugin.reloadPluginData] 默认使用的实例 */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public val dataStorage: PluginDataStorage /** * [JvmPlugin.reloadPluginData] 默认使用的实例 */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public val configStorage: PluginDataStorage public companion object INSTANCE : JarPluginLoader by JarPluginLoaderImpl { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/Annotations.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/Annotations.kt index 4a0e7b595..161120038 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/Annotations.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/Annotations.kt @@ -20,7 +20,7 @@ import kotlin.annotation.AnnotationTarget.* @Retention(AnnotationRetention.SOURCE) @RequiresOptIn(level = RequiresOptIn.Level.ERROR) @Target(PROPERTY, FUNCTION, TYPE, CLASS) -internal annotation class JavaFriendlyAPI +internal annotation class JavaFriendlyApi /** * 标记为一个仅供 mirai-console 内部使用的 API. @@ -32,8 +32,8 @@ internal annotation class JavaFriendlyAPI @RequiresOptIn(level = RequiresOptIn.Level.ERROR) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR, CLASS, FUNCTION, PROPERTY) @MustBeDocumented -public annotation class ConsoleInternalAPI( - val message: String = "" +public annotation class ConsoleInternalApi( + val message: String = "", ) /** @@ -46,6 +46,6 @@ public annotation class ConsoleInternalAPI( @RequiresOptIn(level = RequiresOptIn.Level.WARNING) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR) @MustBeDocumented -public annotation class ConsoleExperimentalAPI( - val message: String = "" +public annotation class ConsoleExperimentalApi( + val message: String = "", ) \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt index 8478bc38b..825d7b89a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt @@ -18,7 +18,7 @@ import net.mamoe.mirai.contact.Member /** * 为简化操作提供的一些工具 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public object ContactUtils { /** * 获取一个 [Bot] 的好友, 群, 或群员. @@ -31,7 +31,7 @@ public object ContactUtils { */ @JvmOverloads @JvmStatic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun Bot.getContact(id: Long, includeMembers: Boolean = false): Contact { return getContactOrNull(id, includeMembers) ?: throw NoSuchElementException("Contact $id not found for bot ${this.id}") @@ -44,7 +44,7 @@ public object ContactUtils { */ @JvmOverloads @JvmStatic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun Bot.getContactOrNull(id: Long, includeMembers: Boolean = false): Contact? { return getFriendOrGroupOrNull(id) ?: kotlin.run { if (includeMembers) { @@ -60,7 +60,7 @@ public object ContactUtils { * 访问顺序为 [Bot.friends] -> [Bot.groups] */ @JvmStatic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun Bot.getFriendOrGroup(id: Long): Contact { return getFriendOrGroupOrNull(id) ?: throw NoSuchElementException("Friend or Group $id not found for bot ${this.id}") @@ -72,7 +72,7 @@ public object ContactUtils { * 访问顺序为 [Bot.friends] -> [Bot.groups] */ @JvmStatic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun Bot.getFriendOrGroupOrNull(id: Long): Contact? { return this.friends.getOrNull(id) ?: this.groups.getOrNull(id) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/CoroutineScopeUtils.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/CoroutineScopeUtils.kt index 647ca62e4..ee2917b80 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/CoroutineScopeUtils.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/CoroutineScopeUtils.kt @@ -15,15 +15,15 @@ import kotlinx.coroutines.* import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public object CoroutineScopeUtils { @JvmStatic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun CoroutineContext.overrideWithSupervisorJob(name: String? = null): CoroutineContext = this + NamedSupervisorJob(name ?: "", this[Job]) @JvmStatic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun CoroutineScope.childScope( name: String? = null, context: CoroutineContext = EmptyCoroutineContext @@ -31,7 +31,7 @@ public object CoroutineScopeUtils { CoroutineScope(this.childScopeContext(name, context)) @JvmStatic - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public fun CoroutineScope.childScopeContext( name: String? = null, context: CoroutineContext = EmptyCoroutineContext @@ -42,7 +42,7 @@ public object CoroutineScopeUtils { } } -@ConsoleExperimentalAPI +@ConsoleExperimentalApi public class NamedSupervisorJob @JvmOverloads constructor( private val name: String, parent: Job? = null diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt index 91309fbba..d10324141 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/MessageScope.kt @@ -104,7 +104,7 @@ public interface MessageScope { * * @suppress 此 API 不稳定, 可能在任何时间被修改 */ - @ConsoleExperimentalAPI + @ConsoleExperimentalApi public val realTarget: Any? /** diff --git a/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/TestMiraiConosle.kt b/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/TestMiraiConosle.kt index 919a4b229..68605851e 100644 --- a/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/TestMiraiConosle.kt +++ b/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/TestMiraiConosle.kt @@ -18,9 +18,9 @@ import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.plugin.DeferredPluginLoader import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleInput -import net.mamoe.mirai.console.util.ConsoleInternalAPI +import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.utils.BotConfiguration import net.mamoe.mirai.utils.LoginSolver @@ -32,12 +32,12 @@ import kotlin.coroutines.CoroutineContext import kotlin.coroutines.resume import kotlin.test.assertNotNull -@OptIn(ConsoleInternalAPI::class) +@OptIn(ConsoleInternalApi::class) fun initTestEnvironment() { object : MiraiConsoleImplementation { override val rootPath: Path = createTempDir().toPath() - @ConsoleExperimentalAPI + @ConsoleExperimentalApi override val frontEndDescription: MiraiConsoleFrontEndDescription get() = object : MiraiConsoleFrontEndDescription { override val name: String diff --git a/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/data/SettingTest.kt b/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/data/SettingTest.kt index 861101fd1..c8f6cde4f 100644 --- a/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/data/SettingTest.kt +++ b/backend/mirai-console/src/test/kotlin/net/mamoe/mirai/console/data/SettingTest.kt @@ -12,12 +12,12 @@ package net.mamoe.mirai.console.data import kotlinx.serialization.json.Json import net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription import net.mamoe.mirai.console.plugin.jvm.KotlinPlugin -import net.mamoe.mirai.console.util.ConsoleInternalAPI +import net.mamoe.mirai.console.util.ConsoleInternalApi import org.junit.jupiter.api.Test import kotlin.test.assertEquals import kotlin.test.assertSame -@OptIn(ConsoleInternalAPI::class) +@OptIn(ConsoleInternalApi::class) internal class PluginDataTest { object MyPlugin : KotlinPlugin( diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index abb6b862a..069901671 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -17,7 +17,7 @@ */ object Versions { - const val core = "1.2.2" + const val core = "1.2.3" const val console = "1.0-M4-dev-5" const val consoleGraphical = "0.0.7" const val consoleTerminal = "0.1.0" diff --git a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt index dd1bd9133..ef82f3c65 100644 --- a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/ConsoleThread.kt @@ -20,14 +20,14 @@ import net.mamoe.mirai.console.command.CommandExecuteStatus import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand import net.mamoe.mirai.console.command.ConsoleCommandSender -import net.mamoe.mirai.console.util.ConsoleInternalAPI +import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.requestInput import net.mamoe.mirai.utils.DefaultLogger import org.jline.reader.UserInterruptException val consoleLogger by lazy { DefaultLogger("console") } -@OptIn(ConsoleInternalAPI::class) +@OptIn(ConsoleInternalApi::class) internal fun startupConsoleThread() { MiraiConsole.launch(CoroutineName("Input")) { while (true) { diff --git a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt index 9bdf2d2ce..97ca52f17 100644 --- a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsoleImplementationPure.kt @@ -17,7 +17,7 @@ "INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER_WARNING", "EXPOSED_SUPER_CLASS" ) -@file:OptIn(ConsoleInternalAPI::class, ConsoleFrontEndImplementation::class) +@file:OptIn(ConsoleInternalApi::class, ConsoleFrontEndImplementation::class) package net.mamoe.mirai.console.pure @@ -34,9 +34,9 @@ import net.mamoe.mirai.console.plugin.DeferredPluginLoader import net.mamoe.mirai.console.plugin.PluginLoader import net.mamoe.mirai.console.plugin.jvm.JarPluginLoader import net.mamoe.mirai.console.pure.ConsoleInputImpl.requestInput -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleInput -import net.mamoe.mirai.console.util.ConsoleInternalAPI +import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.NamedSupervisorJob import net.mamoe.mirai.utils.* import org.fusesource.jansi.Ansi @@ -58,7 +58,7 @@ import java.util.* * * @see MiraiConsolePureLoader CLI 入口点 */ -@ConsoleExperimentalAPI +@ConsoleExperimentalApi class MiraiConsoleImplementationPure @JvmOverloads constructor( override val rootPath: Path = Paths.get("."), diff --git a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt index e52a0ef7e..e1bc7d3f2 100644 --- a/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt +++ b/frontend/mirai-console-pure/src/main/kotlin/net/mamoe/mirai/console/pure/MiraiConsolePureLoader.kt @@ -15,7 +15,7 @@ "INVISIBLE_GETTER", "INVISIBLE_ABSTRACT_MEMBER_FROM_SUPER", ) -@file:OptIn(ConsoleInternalAPI::class) +@file:OptIn(ConsoleInternalApi::class) package net.mamoe.mirai.console.pure @@ -26,8 +26,8 @@ import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.MiraiConsoleImplementation import net.mamoe.mirai.console.MiraiConsoleImplementation.Companion.start import net.mamoe.mirai.console.data.AutoSavePluginDataHolder -import net.mamoe.mirai.console.util.ConsoleExperimentalAPI -import net.mamoe.mirai.console.util.ConsoleInternalAPI +import net.mamoe.mirai.console.util.ConsoleExperimentalApi +import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.utils.DefaultLogger @@ -51,7 +51,7 @@ object MiraiConsolePureLoader { } @Suppress("MemberVisibilityCanBePrivate") - @ConsoleExperimentalAPI + @ConsoleExperimentalApi fun startAsDaemon(instance: MiraiConsoleImplementationPure = MiraiConsoleImplementationPure()) { instance.start() overrideSTD() @@ -61,10 +61,10 @@ object MiraiConsolePureLoader { internal object ConsoleDataHolder : AutoSavePluginDataHolder, CoroutineScope by MiraiConsole.childScope("ConsoleDataHolder") { - @ConsoleExperimentalAPI + @ConsoleExperimentalApi override val autoSaveIntervalMillis: LongRange = 1.minutesToMillis..10.minutesToMillis - @ConsoleExperimentalAPI + @ConsoleExperimentalApi override val dataHolderName: String get() = "Pure" } From 8f1cc48c6be886a99e83346ec85286894613356e Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 16:11:53 +0800 Subject: [PATCH 05/14] Fix buildscript --- backend/mirai-console/build.gradle.kts | 4 ++-- frontend/mirai-console-pure/build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/mirai-console/build.gradle.kts b/backend/mirai-console/build.gradle.kts index 7de97c454..9d927a467 100644 --- a/backend/mirai-console/build.gradle.kts +++ b/backend/mirai-console/build.gradle.kts @@ -45,12 +45,12 @@ kotlin { useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI") useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI") useExperimentalAnnotation("net.mamoe.mirai.console.ConsoleFrontEndImplementation") - useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalAPI") + useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalApi") useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes") useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference") useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") useExperimentalAnnotation("kotlinx.serialization.ExperimentalSerializationApi") - useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleInternalAPI") + useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleInternalApi") } } } diff --git a/frontend/mirai-console-pure/build.gradle.kts b/frontend/mirai-console-pure/build.gradle.kts index 3639b0a7b..57f6dd608 100644 --- a/frontend/mirai-console-pure/build.gradle.kts +++ b/frontend/mirai-console-pure/build.gradle.kts @@ -23,7 +23,7 @@ kotlin { languageSettings.progressiveMode = true languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI") languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI") - languageSettings.useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalAPI") + languageSettings.useExperimentalAnnotation("net.mamoe.mirai.console.util.ConsoleExperimentalApi") languageSettings.useExperimentalAnnotation("net.mamoe.mirai.console.ConsoleFrontEndImplementation") languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes") languageSettings.useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference") From f24042f31efbd82bb1275fd1b6ff711b71cca5d0 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 16:25:24 +0800 Subject: [PATCH 06/14] Install built-in CommandArgumentParsers for PermissionId and PermissibleIdentifier --- .../description/CommandArgumentContext.kt | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt index e071fd0ff..920b7b857 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt @@ -16,6 +16,9 @@ import net.mamoe.mirai.console.command.CommandSender import net.mamoe.mirai.console.command.CompositeCommand import net.mamoe.mirai.console.command.SimpleCommand import net.mamoe.mirai.console.command.description.CommandArgumentContext.ParserPair +import net.mamoe.mirai.console.permission.ExperimentalPermission +import net.mamoe.mirai.console.permission.PermissibleIdentifier +import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.contact.* import kotlin.internal.LowPriorityInOverloadResolution @@ -43,7 +46,7 @@ public interface CommandArgumentContext { */ public data class ParserPair( val klass: KClass, - val parser: CommandArgumentParser + val parser: CommandArgumentParser, ) public operator fun get(klass: KClass): CommandArgumentParser? @@ -63,6 +66,7 @@ public interface CommandArgumentContext { /** * 内建的默认 [CommandArgumentParser] */ + @OptIn(ExperimentalPermission::class) public object Builtins : CommandArgumentContext by (buildCommandArgumentContext { Int::class with IntArgumentParser Byte::class with ByteArgumentParser @@ -79,6 +83,9 @@ public interface CommandArgumentContext { Group::class with ExistingGroupArgumentParser Friend::class with ExistingFriendArgumentParser Bot::class with ExistingBotArgumentParser + + PermissionId::class with PermissionIdArgumentParser + PermissibleIdentifier::class with PermissibleIdentifierArgumentParser }) } @@ -134,7 +141,7 @@ public operator fun CommandArgumentContext.plus(replacer: List>): */ @Suppress("UNCHECKED_CAST") public class SimpleCommandArgumentContext( - public val list: List> + public val list: List>, ) : CommandArgumentContext { override fun get(klass: KClass): CommandArgumentParser? = (this.list.firstOrNull { klass == it.klass }?.parser @@ -208,7 +215,7 @@ public class CommandArgumentContextBuilder : MutableList> by mutab @JvmSynthetic @LowPriorityInOverloadResolution public inline infix fun KClass.with( - crossinline parser: CommandArgumentParser.(s: String, sender: CommandSender) -> T + crossinline parser: CommandArgumentParser.(s: String, sender: CommandSender) -> T, ): CommandArgumentContextBuilder { add(ParserPair(this, object : CommandArgumentParser { override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender) @@ -221,7 +228,7 @@ public class CommandArgumentContextBuilder : MutableList> by mutab */ @JvmSynthetic public inline infix fun KClass.with( - crossinline parser: CommandArgumentParser.(s: String) -> T + crossinline parser: CommandArgumentParser.(s: String) -> T, ): CommandArgumentContextBuilder { add(ParserPair(this, object : CommandArgumentParser { override fun parse(raw: String, sender: CommandSender): T = parser(raw) @@ -241,7 +248,7 @@ public class CommandArgumentContextBuilder : MutableList> by mutab @ConsoleExperimentalApi @JvmSynthetic public inline infix fun add( - crossinline parser: CommandArgumentParser<*>.(s: String) -> T + crossinline parser: CommandArgumentParser<*>.(s: String) -> T, ): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser { override fun parse(raw: String, sender: CommandSender): T = parser(raw) } @@ -253,7 +260,7 @@ public class CommandArgumentContextBuilder : MutableList> by mutab @JvmSynthetic @LowPriorityInOverloadResolution public inline infix fun add( - crossinline parser: CommandArgumentParser<*>.(s: String, sender: CommandSender) -> T + crossinline parser: CommandArgumentParser<*>.(s: String, sender: CommandSender) -> T, ): CommandArgumentContextBuilder = T::class with object : CommandArgumentParser { override fun parse(raw: String, sender: CommandSender): T = parser(raw, sender) } From 8a01dcc556685a7794e9213cc0a658e18b5f08f8 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 16:25:36 +0800 Subject: [PATCH 07/14] Support parsing self for PermissibleIdentifierArgumentParser --- .../command/description/CommandArgumentParserBuiltins.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt index b78fc129c..3484296f1 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt @@ -320,7 +320,8 @@ public object PermissionIdArgumentParser : CommandArgumentParser { @ExperimentalPermission public object PermissibleIdentifierArgumentParser : CommandArgumentParser { override fun parse(raw: String, sender: CommandSender): PermissibleIdentifier { - return kotlin.runCatching { AbstractPermissibleIdentifier.parseFromString(raw) }.getOrElse { + return if (raw == "~") sender.identifier + else kotlin.runCatching { AbstractPermissibleIdentifier.parseFromString(raw) }.getOrElse { illegalArgument("无法解析 $raw 为 PermissibleIdentifier") } } From 8fc4da127b1352043c603ea31615e739f587cfe9 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 16:25:58 +0800 Subject: [PATCH 08/14] Extract executeCommandInternal --- .../command/executeCommandInternal.kt | 64 +++++++++++++++++++ .../console/internal/command/internal.kt | 53 +-------------- 2 files changed, 65 insertions(+), 52 deletions(-) create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt new file mode 100644 index 000000000..57414b6b5 --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt @@ -0,0 +1,64 @@ +/* + * Copyright 2019-2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.console.internal.command + +import net.mamoe.mirai.console.command.* +import net.mamoe.mirai.console.permission.ExperimentalPermission +import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission +import net.mamoe.mirai.message.data.MessageChain +import net.mamoe.mirai.message.data.asMessageChain + +@OptIn(ExperimentalPermission::class) +@JvmSynthetic +@Throws(CommandExecutionException::class) +internal suspend fun CommandSender.executeCommandInternal( + command: Command, + args: MessageChain, + commandName: String, + checkPermission: Boolean, +): CommandExecuteResult { + if (checkPermission && !command.permission.testPermission(this)) { + return CommandExecuteResult.PermissionDenied(command, commandName) + } + + kotlin.runCatching { + command.onCommand(this, args) + }.fold( + onSuccess = { + return CommandExecuteResult.Success( + commandName = commandName, + command = command, + args = args + ) + }, + onFailure = { + return CommandExecuteResult.ExecutionFailed( + commandName = commandName, + command = command, + exception = it, + args = args + ) + } + ) +} + + +@JvmSynthetic +internal suspend fun CommandSender.executeCommandInternal( + messages: Any, + commandName: String, + checkPermission: Boolean, +): CommandExecuteResult { + val command = + CommandManagerImpl.matchCommand(commandName) ?: return CommandExecuteResult.CommandNotFound(commandName) + val args = messages.flattenCommandComponents() + + return executeCommandInternal(command, args.drop(1).asMessageChain(), commandName, checkPermission) +} diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt index 650a254f5..876ca8f95 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt @@ -9,16 +9,13 @@ package net.mamoe.mirai.console.internal.command -import net.mamoe.mirai.console.command.* +import net.mamoe.mirai.console.command.Command import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.PermissionService -import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission import net.mamoe.mirai.contact.Group import net.mamoe.mirai.contact.Member -import net.mamoe.mirai.message.data.MessageChain -import net.mamoe.mirai.message.data.asMessageChain import kotlin.math.max import kotlin.math.min @@ -148,51 +145,3 @@ internal fun Command.createOrFindCommandPermission(parent: Permission): Permissi } //// internal - -@OptIn(ExperimentalPermission::class) -@JvmSynthetic -@Throws(CommandExecutionException::class) -internal suspend fun CommandSender.executeCommandInternal( - command: Command, - args: MessageChain, - commandName: String, - checkPermission: Boolean -): CommandExecuteResult { - if (checkPermission && !command.permission.testPermission(this)) { - return CommandExecuteResult.PermissionDenied(command, commandName) - } - - kotlin.runCatching { - command.onCommand(this, args) - }.fold( - onSuccess = { - return CommandExecuteResult.Success( - commandName = commandName, - command = command, - args = args - ) - }, - onFailure = { - return CommandExecuteResult.ExecutionFailed( - commandName = commandName, - command = command, - exception = it, - args = args - ) - } - ) -} - - -@JvmSynthetic -internal suspend fun CommandSender.executeCommandInternal( - messages: Any, - commandName: String, - checkPermission: Boolean -): CommandExecuteResult { - val command = - CommandManagerImpl.matchCommand(commandName) ?: return CommandExecuteResult.CommandNotFound(commandName) - val args = messages.flattenCommandComponents() - - return executeCommandInternal(command, args.drop(1).asMessageChain(), commandName, checkPermission) -} From c7cde8e7905d0f26fc73b4adf2397ab2807a6b6c Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 16:26:12 +0800 Subject: [PATCH 09/14] Fix PermissibleIdentifier.allParentsWithSelf --- .../net/mamoe/mirai/console/permission/PermissibleIdentifier.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt index 6db38f796..515b59164 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt @@ -32,7 +32,7 @@ public interface PermissibleIdentifier { private fun PermissibleIdentifier.allParentsWithSelf(): Sequence { return sequence { yield(this@allParentsWithSelf) - yieldAll(parents.asSequence()) + yieldAll(parents.asSequence().flatMap { it.allParentsWithSelf() }) } } } From 7b8e9cc1c66dc9b74ab6b2819cc690b7fc57d967 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 18:51:40 +0800 Subject: [PATCH 10/14] Review: Permission, PermissionService; Lots of improvements; Rename Permissible to Permittee, rename PermissibleIdentifier to PermitteeId; Add docs for Permission system; Remove ExperimentalPermission annotations on some targets --- .../mirai/console/command/BuiltInCommands.kt | 444 ++---------------- .../mamoe/mirai/console/command/Command.kt | 9 +- .../mirai/console/command/CommandSender.kt | 33 +- .../description/CommandArgumentContext.kt | 4 +- .../CommandArgumentParserBuiltins.kt | 16 +- .../console/extension/ComponentStorage.kt | 2 +- .../MiraiConsoleImplementationBridge.kt | 2 +- .../AbstractConcurrentPermissionService.kt | 23 +- .../permission/BuiltInPermissionServices.kt | 51 +- .../permission/parseFromStringImpl.kt | 80 ++++ .../console/internal/util/CommonUtils.kt | 30 ++ .../permission/PermissibleIdentifier.kt | 186 -------- .../mirai/console/permission/Permission.kt | 80 ++-- .../mirai/console/permission/PermissionId.kt | 35 +- .../permission/PermissionIdNamespace.kt | 2 - .../permission/PermissionImplementation.kt | 23 + .../permission/PermissionNotFoundException.kt | 15 - ...=> PermissionRegistryConflictException.kt} | 12 +- .../console/permission/PermissionService.kt | 130 +++-- .../{Permissible.kt => Permittee.kt} | 12 +- .../mirai/console/permission/PermitteeId.kt | 307 ++++++++++++ .../mamoe/mirai/console/util/ContactUtils.kt | 22 +- 22 files changed, 744 insertions(+), 774 deletions(-) rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/{ => internal}/permission/AbstractConcurrentPermissionService.kt (64%) rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/{ => internal}/permission/BuiltInPermissionServices.kt (72%) create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/parseFromStringImpl.kt create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/CommonUtils.kt delete mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionImplementation.kt delete mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionNotFoundException.kt rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/{DuplicatedPermissionRegistrationException.kt => PermissionRegistryConflictException.kt} (68%) rename backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/{Permissible.kt => Permittee.kt} (62%) create mode 100644 backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermitteeId.kt diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt index ad390ef01..827a216d8 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt @@ -12,22 +12,20 @@ package net.mamoe.mirai.console.command import kotlinx.coroutines.* import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock -import net.mamoe.mirai.Bot import net.mamoe.mirai.alsoLogin import net.mamoe.mirai.console.MiraiConsole import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register import net.mamoe.mirai.console.command.description.* import net.mamoe.mirai.console.internal.command.CommandManagerImpl import net.mamoe.mirai.console.internal.command.CommandManagerImpl.allRegisteredCommands -import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip +import net.mamoe.mirai.console.internal.util.runIgnoreException import net.mamoe.mirai.console.permission.* import net.mamoe.mirai.console.permission.PermissionService.Companion.denyPermission import net.mamoe.mirai.console.permission.PermissionService.Companion.findCorrespondingPermissionOrFail -import net.mamoe.mirai.console.permission.PermissionService.Companion.getGrantedPermissions +import net.mamoe.mirai.console.permission.PermissionService.Companion.getPermittedPermissions import net.mamoe.mirai.console.permission.PermissionService.Companion.grantPermission import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleInternalApi -import net.mamoe.mirai.contact.* import net.mamoe.mirai.event.events.EventCancelledException import net.mamoe.mirai.message.nextMessageOrNull import net.mamoe.mirai.utils.secondsToMillis @@ -37,20 +35,26 @@ import kotlin.system.exitProcess @ConsoleExperimentalApi @Suppress("EXPOSED_SUPER_INTERFACE") -public interface BuiltInCommand : Command, BuiltInCommandInternal +public interface BuiltInCommand : Command // for identification -internal interface BuiltInCommandInternal : Command +internal interface BuiltInCommandInternal : Command, BuiltInCommand /** * 内建指令列表 */ -@ConsoleExperimentalApi @Suppress("unused") @OptIn(ExperimentalPermission::class) public object BuiltInCommands { + @ConsoleExperimentalApi + public val rootPermission: Permission by lazy { + PermissionService.INSTANCE.register( + PermissionId("console", "*"), + "The parent of any built-in commands" + ) + } - public val all: Array by lazy { + internal val all: Array by lazy { this::class.nestedClasses.mapNotNull { it.objectInstance as? Command }.toTypedArray() } @@ -63,8 +67,8 @@ public object BuiltInCommands { public object HelpCommand : SimpleCommand( ConsoleCommandOwner, "help", description = "Command list", - parentPermission = RootConsoleBuiltInPermission, - ), BuiltInCommand { + parentPermission = rootPermission, + ), BuiltInCommandInternal { @Handler public suspend fun CommandSender.handle() { sendMessage( @@ -83,8 +87,8 @@ public object BuiltInCommands { public object StopCommand : SimpleCommand( ConsoleCommandOwner, "stop", "shutdown", "exit", description = "Stop the whole world.", - parentPermission = RootConsoleBuiltInPermission, - ), BuiltInCommand { + parentPermission = rootPermission, + ), BuiltInCommandInternal { private val closingLock = Mutex() @@ -94,16 +98,16 @@ public object BuiltInCommands { closingLock.withLock { sendMessage("Stopping mirai-console") kotlin.runCatching { - ignoreException { MiraiConsole.job.cancelAndJoin() } + runIgnoreException { MiraiConsole.job.cancelAndJoin() } }.fold( onSuccess = { - ignoreException { sendMessage("mirai-console stopped successfully.") } + runIgnoreException { sendMessage("mirai-console stopped successfully.") } }, onFailure = { if (it is CancellationException) return@fold @OptIn(ConsoleInternalApi::class) MiraiConsole.mainLogger.error("Exception in stop", it) - ignoreException { + runIgnoreException { sendMessage( it.localizedMessage ?: it.message ?: it.toString() ) @@ -119,8 +123,8 @@ public object BuiltInCommands { public object LoginCommand : SimpleCommand( ConsoleCommandOwner, "login", "登录", description = "Log in a bot account.", - parentPermission = RootConsoleBuiltInPermission, - ), BuiltInCommand { + parentPermission = rootPermission, + ), BuiltInCommandInternal { @Handler public suspend fun CommandSender.handle(id: Long, password: String) { kotlin.runCatching { @@ -149,31 +153,37 @@ public object BuiltInCommands { ConsoleCommandOwner, "permission", "权限", "perm", description = "Manage permissions", overrideContext = buildCommandArgumentContext { - PermissibleIdentifier::class with PermissibleIdentifierArgumentParser + PermitteeId::class with PermissibleIdentifierArgumentParser Permission::class with PermissionIdArgumentParser.map { id -> kotlin.runCatching { id.findCorrespondingPermissionOrFail() }.getOrElse { illegalArgument("指令不存在: $id", it) } } }, - parentPermission = RootConsoleBuiltInPermission, - ), BuiltInCommand { + parentPermission = rootPermission, + ), BuiltInCommandInternal { // TODO: 2020/9/10 improve Permission command - @SubCommand - public suspend fun CommandSender.grant(target: PermissibleIdentifier, permission: Permission) { + @SubCommand("permit", "grant", "add") + public suspend fun CommandSender.permit(target: PermitteeId, permission: Permission) { target.grantPermission(permission) sendMessage("OK") } - @SubCommand - public suspend fun CommandSender.deny(target: PermissibleIdentifier, permission: Permission) { - target.denyPermission(permission) + @SubCommand("cancel", "deny", "remove") + public suspend fun CommandSender.cancel(target: PermitteeId, permission: Permission) { + target.denyPermission(permission, false) sendMessage("OK") } - @SubCommand("grantedPermissions", "gp") - public suspend fun CommandSender.grantedPermissions(target: PermissibleIdentifier) { - val grantedPermissions = target.getGrantedPermissions() + @SubCommand("cancelAll", "denyAll", "removeAll") + public suspend fun CommandSender.cancelAll(target: PermitteeId, permission: Permission) { + target.denyPermission(permission, true) + sendMessage("OK") + } + + @SubCommand("permittedPermissions", "pp", "grantedPermissions", "gp") + public suspend fun CommandSender.permittedPermissions(target: PermitteeId) { + val grantedPermissions = target.getPermittedPermissions() sendMessage(grantedPermissions.joinToString("\n") { it.id.toString() }) } @@ -182,380 +192,4 @@ public object BuiltInCommands { sendMessage(PermissionService.INSTANCE.getRegisteredPermissions().joinToString("\n") { it.id.toString() }) } } -} - -internal inline fun ignoreException(block: () -> R): R? { - try { - return block() - } catch (e: Throwable) { - if (e is E) return null - throw e - } -} - -internal inline fun ignoreException(block: () -> Unit): Unit? { - try { - return block() - } catch (e: Throwable) { - if (e is E) return null - throw e - } -} - -internal fun ContactOrBot.render(): String { - return when (this) { - is Bot -> "Bot $nick($id)" - is Group -> "Group $name($id)" - is Friend -> "Friend $nick($id)" - is Member -> "Friend $nameCardOrNick($id)" - else -> error("Illegal type for ContactOrBot: ${this::class.qualifiedNameOrTip}") - } -} - -/* - -/** - * Some defaults commands are recommend to be replaced by plugin provided commands - */ -internal object DefaultCommands { - internal val commandPrefix = "mirai.command.prefix".property() ?: "/" - private suspend fun CommandSender.login(account: Long, password: String) { - MiraiConsole.logger("[Bot Login]", 0, "login...") - try { - MiraiConsole.frontEnd.prePushBot(account) - val bot = Bot(account, password) { - fileBasedDeviceInfo(MiraiConsole.path + "/device.json") - this.loginSolver = MiraiConsole.frontEnd.createLoginSolver() - this.botLoggerSupplier = { - SimpleLogger("BOT $account]") { _, message, e -> - MiraiConsole.logger("[BOT $account]", account, message) - if (e != null) { - MiraiConsole.logger("[NETWORK ERROR]", account, e)//因为在一页 所以可以不打QQ - } - } - } - this.networkLoggerSupplier = { - SimpleLogger("BOT $account") { _, message, e -> - MiraiConsole.logger("[NETWORK]", account, message)//因为在一页 所以可以不打QQ - if (e != null) { - MiraiConsole.logger("[NETWORK ERROR]", account, e)//因为在一页 所以可以不打QQ - } - } - } - } - bot.login() - MiraiConsole.subscribeMessages { - startsWith(commandPrefix) { message -> - if (this.bot != bot) return@startsWith - - if (bot.checkManager(this.sender.id)) { - val sender = if (this is GroupMessageEvent) { - GroupContactCommandSender(bot,this.sender, this.subject) - } else { - ContactCommandSender(bot,this.subject) - } - CommandManager.runCommand( - sender, message - ) - } - } - } - sendMessage("$account login successes") - MiraiConsole.frontEnd.pushBot(bot) - } catch (e: Exception) { - sendMessage("$account login failed -> " + e.message) - } - } - - private fun String.property(): String? = System.getProperty(this) - - @JvmSynthetic - internal fun tryLoginAuto() { - // For java -Dmirai.account=10086 -Dmirai.password=Password -jar mirai-console-wrapper-X.jar - val account = ("mirai.account".property() ?: return).toLong() - val password = "mirai.password".property() ?: "mirai.passphrase".property() ?: "mirai.passwd".property() - if (password == null) { - MiraiConsole.logger.invoke( - SimpleLogger.LogPriority.ERROR, "[AUTO LOGIN]", account, - "Find the account to be logged in, but no password specified" - ) - return - } - GlobalScope.launch { - ConsoleCommandSender.login(account, password) - } - } - - operator fun invoke() { - registerConsoleCommands { - name = "manager" - description = "Add a manager" - onCommand { it -> - if (this !is ConsoleCommandSender) { - sendMessage("请在后台使用该指令") - return@onCommand false - } - if (it.size < 2) { - MiraiConsole.logger("[Bot Manager]", 0, "/manager add [bot ID] [Manager ID]") - MiraiConsole.logger("[Bot Manager]", 0, "/manager remove [bot ID] [Manager ID]") - MiraiConsole.logger("[Bot Manager]", 0, "/manager list [bot ID]") - return@onCommand true - } - val botId = try { - it[1].toLong() - } catch (e: Exception) { - MiraiConsole.logger("[Bot Manager]", 0, it[1] + " 不是一个Bot的ID") - return@onCommand false - } - val bot = MiraiConsole.getBotOrNull(botId) - if (bot == null) { - MiraiConsole.logger("[Bot Manager]", 0, "$botId 没有在Console中登陆") - return@onCommand false - } - when (it[0]) { - "add" -> { - if (it.size < 3) { - MiraiConsole.logger("[Bot Manager]", 0, "/manager add [bot ID] [Manager ID]") - return@onCommand true - } - val adminID = try { - it[2].toLong() - } catch (e: Exception) { - MiraiConsole.logger("[Bot Manager]", 0, it[2] + " 不是一个ID") - return@onCommand false - } - if (bot.addManager(adminID)) { - MiraiConsole.logger("[Bot Manager]", 0, it[2] + "增加成功") - } else { - MiraiConsole.logger("[Bot Manager]", 0, it[2] + "已经是一个manager了") - } - } - "remove" -> { - if (it.size < 3) { - MiraiConsole.logger("[Bot Manager]", 0, "/manager remove [bot ID] [Manager ID]") - return@onCommand true - } - val adminID = try { - it[2].toLong() - } catch (e: Exception) { - MiraiConsole.logger("[Bot Manager]", 0, it[1] + " 不是一个ID") - return@onCommand false - } - if (!bot.checkManager(adminID)) { - MiraiConsole.logger("[Bot Manager]", 0, it[2] + "本身不是一个Manager") - return@onCommand true - } - bot.removeManager(adminID) - MiraiConsole.logger("[Bot Manager]", 0, it[2] + "移除成功") - } - "list" -> { - bot.managers.forEach { - MiraiConsole.logger("[Bot Manager]", 0, " -> $it") - } - } - } - return@onCommand true - } - } - - registerConsoleCommands { - name = "login" - description = "机器人登录" - onCommand { - if (this !is ConsoleCommandSender) { - sendMessage("请在后台使用该指令") - return@onCommand false - } - if (it.size < 2) { - MiraiConsole.logger("\"/login qq password \" to login a bot") - MiraiConsole.logger("\"/login qq号 qq密码 \" 来登录一个BOT") - return@onCommand false - } - val qqNumber = it[0].toLong() - val qqPassword = it[1] - login(qqNumber, qqPassword) - true - } - } - - registerConsoleCommands { - name = "status" - description = "获取状态" - onCommand { args -> - when (args.size) { - 0 -> { - sendMessage("当前有" + botInstances.size + "个BOT在线") - } - 1 -> { - val bot = args[0] - var find = false - botInstances.forEach { - if (it.id.toString().contains(bot)) { - find = true - appendMessage( - "" + it.id + ": 在线中; 好友数量:" + it.friends.size + "; 群组数量:" + it.groups.size - ) - } - } - if (!find) { - sendMessage("没有找到BOT$bot") - } - } - } - true - } - } - - - registerConsoleCommands { - name = "say" - description = "聊天功能演示" - onCommand { - if (it.size < 2) { - MiraiConsole.logger("say [好友qq号或者群号] [测试消息] //将默认使用第一个BOT") - MiraiConsole.logger("say [bot号] [好友qq号或者群号] [测试消息]") - return@onCommand false - } - val bot: Bot? = if (it.size == 2) { - if (botInstances.isEmpty()) { - MiraiConsole.logger("还没有BOT登录") - return@onCommand false - } - botInstances[0] - } else { - MiraiConsole.getBotOrNull(it[0].toLong()) - } - if (bot == null) { - MiraiConsole.logger("没有找到BOT") - return@onCommand false - } - val target = it[it.size - 2].toLong() - val message = it[it.size - 1] - try { - val contact = bot.getFriendOrNull(target) ?: bot.getGroup(target) - contact.sendMessage(message) - MiraiConsole.logger("消息已推送") - } catch (e: NoSuchElementException) { - MiraiConsole.logger("没有找到群或好友 号码为${target}") - return@onCommand false - } - true - } - } - - - registerConsoleCommands { - name = "plugins" - alias = listOf("plugin") - description = "获取插件列表" - onCommand { - PluginManager.getAllPluginDescriptions().let { descriptions -> - descriptions.forEach { - appendMessage("\t" + it.name + " v" + it.version + " by " + it.author + " " + it.info) - } - appendMessage("加载了" + descriptions.size + "个插件") - true - } - } - } - - registerConsoleCommands { - name = "command" - alias = listOf("commands", "help", "helps") - description = "获取指令列表" - onCommand { - CommandManager.commands.toSet().let { commands -> - var size = 0 - appendMessage("")//\n - commands.forEach { - ++size - appendMessage("-> " + it.name + " :" + it.description) - } - appendMessage("""共有${size}条指令""") - } - true - } - } - - registerConsoleCommands { - name = "about" - description = "About Mirai-Console" - onCommand { - appendMessage("v${MiraiConsole.version} ${MiraiConsole.build} is still in testing stage, major features are available") - appendMessage("now running under ${MiraiConsole.path}") - appendMessage("在Github中获取项目最新进展: https://github.com/mamoe/mirai") - appendMessage("Mirai为开源项目,请自觉遵守开源项目协议") - appendMessage("Powered by Mamoe Technologies and contributors") - true - } - } - - registerConsoleCommands { - name = "reload" - alias = listOf("reloadPlugins") - description = "重新加载全部插件" - onCommand { - PluginManager.reloadPlugins() - sendMessage("重新加载完成") - true - } - } - - registerConsoleCommands { - name = "install" - description = "Install plugin from PluginCenter" - usage = "/install [plugin-name] to install plugin or /install [page-num] to show list " - onCommand { args -> - - val center = MiraiConsole.frontEnd.pluginCenter - - suspend fun showPage(num: Int) { - sendMessage("正在连接 " + center.name) - val list = center.fetchPlugin(num) - if (list.isEmpty()) { - sendMessage("页码过大") - return - } - sendMessage("显示插件列表第 $num 页") - appendMessage("\n") - list.values.forEach { - appendMessage("=> " + it.name + " ;作者: " + it.author + " ;介绍: " + it.description) - } - sendMessage("使用 /install ${num + 1} 查看下一页") - } - - suspend fun installPlugin(name: String) { - sendMessage("正在连接 " + center.name) - val plugin = center.findPlugin(name) - if (plugin == null) { - sendMessage("插件未找到, 请注意大小写") - return - } - sendMessage("正在安装 " + plugin.name) - try { - center.downloadPlugin(name) {} - sendMessage("安装 " + plugin.name + " 成功, 请重启服务器以更新") - } catch (e: Exception) { - sendMessage("安装 " + plugin.name + " 失败, " + (e.message ?: "未知原因")) - } - } - - if (args.isEmpty()) { - showPage(1) - } else { - val arg = args[0] - - val id = arg.toIntOrNull() ?: 0 - if (id > 0) { - showPage(id) - } else { - installPlugin(arg) - } - } - true - } - } - } -} - - */ \ No newline at end of file +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt index 2bbdc769a..5a29b2559 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt @@ -54,7 +54,6 @@ public interface Command { /** * 指令权限 */ - @ExperimentalPermission public val permission: Permission /** @@ -85,13 +84,13 @@ public interface Command { @JvmStatic public val Command.primaryName: String get() = names[0] + + @JvmSynthetic + public suspend inline fun Command.onCommand(sender: CommandSender, args: MessageChain): Unit = + sender.run { onCommand(args) } } } -@JvmSynthetic -public suspend inline fun Command.onCommand(sender: CommandSender, args: MessageChain): Unit = - sender.run { onCommand(args) } - /** * [Command] 的基础实现 * diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt index 1aa13de3d..10a1bd6d9 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt @@ -32,10 +32,10 @@ import net.mamoe.mirai.console.internal.MiraiConsoleImplementationBridge import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip import net.mamoe.mirai.console.internal.data.castOrNull import net.mamoe.mirai.console.internal.plugin.rootCauseOrSelf -import net.mamoe.mirai.console.permission.AbstractPermissibleIdentifier +import net.mamoe.mirai.console.permission.AbstractPermitteeId import net.mamoe.mirai.console.permission.ExperimentalPermission -import net.mamoe.mirai.console.permission.Permissible -import net.mamoe.mirai.console.permission.PermissibleIdentifier +import net.mamoe.mirai.console.permission.Permittee +import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScope import net.mamoe.mirai.console.util.CoroutineScopeUtils.childScopeContext @@ -137,7 +137,7 @@ import kotlin.internal.LowPriorityInOverloadResolution * @see asCommandSender */ @OptIn(ExperimentalPermission::class) -public interface CommandSender : CoroutineScope, Permissible { +public interface CommandSender : CoroutineScope, Permittee { /** * 与这个 [CommandSender] 相关的 [Bot]. * 当通过控制台执行时为 `null`. @@ -504,6 +504,9 @@ public fun CommandSender.getBotOrNull(): Bot? { /** * 控制台指令执行者. 代表由控制台执行指令 + * + * 控制台拥有一切指令的执行权限. + * * @see INSTANCE */ // 前端实现 @@ -515,7 +518,7 @@ public abstract class ConsoleCommandSender @ConsoleFrontEndImplementation constr public final override fun toString(): String = NAME @ExperimentalPermission - public final override val identifier: PermissibleIdentifier = AbstractPermissibleIdentifier.Console + public final override val permitteeId: AbstractPermitteeId.Console = AbstractPermitteeId.Console public companion object INSTANCE : ConsoleCommandSender(), CoroutineScope { public const val NAME: String = "ConsoleCommandSender" @@ -607,13 +610,13 @@ public sealed class AbstractUserCommandSender : UserCommandSender, AbstractComma * @see FriendCommandSenderOnMessage 代表一个真实的 [好友][Friend] 主动在私聊消息执行指令 */ public open class FriendCommandSender internal constructor( - public final override val user: Friend + public final override val user: Friend, ) : AbstractUserCommandSender(), CoroutineScope by user.childScope("FriendCommandSender") { public override val subject: Contact get() = user public override fun toString(): String = "FriendCommandSender($user)" @ExperimentalPermission - public override val identifier: PermissibleIdentifier = AbstractPermissibleIdentifier.ExactFriend(user.id) + public override val permitteeId: PermitteeId = AbstractPermitteeId.ExactFriend(user.id) @JvmBlockingBridge public override suspend fun sendMessage(message: String): MessageReceipt = sendMessage(PlainText(message)) @@ -627,7 +630,7 @@ public open class FriendCommandSender internal constructor( * @see MemberCommandSenderOnMessage 代表一个真实的 [群员][Member] 主动在群内发送消息执行指令. */ public open class MemberCommandSender internal constructor( - public final override val user: Member + public final override val user: Member, ) : AbstractUserCommandSender(), GroupAwareCommandSender, CoroutineScope by user.childScope("MemberCommandSender") { @@ -636,7 +639,7 @@ public open class MemberCommandSender internal constructor( public override fun toString(): String = "MemberCommandSender($user)" @ExperimentalPermission - public override val identifier: PermissibleIdentifier = AbstractPermissibleIdentifier.ExactMember(group.id, user.id) + public override val permitteeId: PermitteeId = AbstractPermitteeId.ExactMember(group.id, user.id) @JvmBlockingBridge public override suspend fun sendMessage(message: String): MessageReceipt = sendMessage(PlainText(message)) @@ -650,7 +653,7 @@ public open class MemberCommandSender internal constructor( * @see TempCommandSenderOnMessage 代表一个 [群员][Member] 主动在临时会话发送消息执行指令 */ public open class TempCommandSender internal constructor( - public final override val user: Member + public final override val user: Member, ) : AbstractUserCommandSender(), GroupAwareCommandSender, CoroutineScope by user.childScope("TempCommandSender") { @@ -659,8 +662,8 @@ public open class TempCommandSender internal constructor( public override fun toString(): String = "TempCommandSender($user)" @ExperimentalPermission - public override val identifier: PermissibleIdentifier = - AbstractPermissibleIdentifier.ExactTemp(user.group.id, user.id) + public override val permitteeId: PermitteeId = + AbstractPermitteeId.ExactTemp(user.group.id, user.id) @JvmBlockingBridge public override suspend fun sendMessage(message: String): MessageReceipt = sendMessage(PlainText(message)) @@ -695,7 +698,7 @@ public interface CommandSenderOnMessage : * @see FriendCommandSender 代表一个 [好友][Friend] 执行指令, 但不一定是通过私聊方式 */ public class FriendCommandSenderOnMessage internal constructor( - public override val fromEvent: FriendMessageEvent + public override val fromEvent: FriendMessageEvent, ) : FriendCommandSender(fromEvent.sender), CommandSenderOnMessage, MessageEventExtensions by fromEvent { @@ -708,7 +711,7 @@ public class FriendCommandSenderOnMessage internal constructor( * @see MemberCommandSender 代表一个 [群员][Member] 执行指令, 但不一定是通过群内发消息方式 */ public class MemberCommandSenderOnMessage internal constructor( - public override val fromEvent: GroupMessageEvent + public override val fromEvent: GroupMessageEvent, ) : MemberCommandSender(fromEvent.sender), CommandSenderOnMessage, MessageEventExtensions by fromEvent { @@ -721,7 +724,7 @@ public class MemberCommandSenderOnMessage internal constructor( * @see TempCommandSender 代表一个 [群员][Member] 通过临时会话执行指令, 但不一定是通过私聊方式 */ public class TempCommandSenderOnMessage internal constructor( - public override val fromEvent: TempMessageEvent + public override val fromEvent: TempMessageEvent, ) : TempCommandSender(fromEvent.sender), CommandSenderOnMessage, MessageEventExtensions by fromEvent { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt index 920b7b857..714bc639a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt @@ -17,8 +17,8 @@ import net.mamoe.mirai.console.command.CompositeCommand import net.mamoe.mirai.console.command.SimpleCommand import net.mamoe.mirai.console.command.description.CommandArgumentContext.ParserPair import net.mamoe.mirai.console.permission.ExperimentalPermission -import net.mamoe.mirai.console.permission.PermissibleIdentifier import net.mamoe.mirai.console.permission.PermissionId +import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.contact.* import kotlin.internal.LowPriorityInOverloadResolution @@ -85,7 +85,7 @@ public interface CommandArgumentContext { Bot::class with ExistingBotArgumentParser PermissionId::class with PermissionIdArgumentParser - PermissibleIdentifier::class with PermissibleIdentifierArgumentParser + PermitteeId::class with PermissibleIdentifierArgumentParser }) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt index 3484296f1..91cfffcae 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt @@ -13,10 +13,10 @@ import net.mamoe.mirai.Bot import net.mamoe.mirai.console.command.* import net.mamoe.mirai.console.command.CommandSender.Companion.asCommandSender import net.mamoe.mirai.console.internal.command.fuzzySearchMember -import net.mamoe.mirai.console.permission.AbstractPermissibleIdentifier +import net.mamoe.mirai.console.permission.AbstractPermitteeId import net.mamoe.mirai.console.permission.ExperimentalPermission -import net.mamoe.mirai.console.permission.PermissibleIdentifier import net.mamoe.mirai.console.permission.PermissionId +import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.contact.* import net.mamoe.mirai.getFriendOrNull import net.mamoe.mirai.getGroupOrNull @@ -318,17 +318,17 @@ public object PermissionIdArgumentParser : CommandArgumentParser { } @ExperimentalPermission -public object PermissibleIdentifierArgumentParser : CommandArgumentParser { - override fun parse(raw: String, sender: CommandSender): PermissibleIdentifier { - return if (raw == "~") sender.identifier - else kotlin.runCatching { AbstractPermissibleIdentifier.parseFromString(raw) }.getOrElse { +public object PermissibleIdentifierArgumentParser : CommandArgumentParser { + override fun parse(raw: String, sender: CommandSender): PermitteeId { + return if (raw == "~") sender.permitteeId + else kotlin.runCatching { AbstractPermitteeId.parseFromString(raw) }.getOrElse { illegalArgument("无法解析 $raw 为 PermissibleIdentifier") } } - override fun parse(raw: MessageContent, sender: CommandSender): PermissibleIdentifier { + override fun parse(raw: MessageContent, sender: CommandSender): PermitteeId { if (raw is At) { - return ExistingUserArgumentParser.parse(raw, sender).asCommandSender(false).identifier + return ExistingUserArgumentParser.parse(raw, sender).asCommandSender(false).permitteeId } return super.parse(raw, sender) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt index e7ffcc587..6886e3da4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt @@ -65,7 +65,7 @@ public class ScopedComponentStorage( } /** - * 注册一个扩展 + * 注册一个 [PermissionService] */ @ExperimentalPermission public fun contributePermissionService( diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt index 7109b7c0e..f9ebc4e55 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt @@ -36,9 +36,9 @@ import net.mamoe.mirai.console.internal.data.builtins.AutoLoginConfig import net.mamoe.mirai.console.internal.data.builtins.ConsoleDataScope import net.mamoe.mirai.console.internal.data.castOrNull import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSelector +import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl import net.mamoe.mirai.console.internal.util.autoHexToBytes -import net.mamoe.mirai.console.permission.BuiltInPermissionService import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService.Companion.grantPermission diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/AbstractConcurrentPermissionService.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/AbstractConcurrentPermissionService.kt similarity index 64% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/AbstractConcurrentPermissionService.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/AbstractConcurrentPermissionService.kt index 21563301a..7bdc4bedf 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/AbstractConcurrentPermissionService.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/AbstractConcurrentPermissionService.kt @@ -7,10 +7,11 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -package net.mamoe.mirai.console.permission +package net.mamoe.mirai.console.internal.permission import net.mamoe.mirai.console.data.PluginDataExtensions -import net.mamoe.mirai.console.permission.PermissibleIdentifier.Companion.grantedWith +import net.mamoe.mirai.console.permission.* +import net.mamoe.mirai.console.permission.PermitteeId.Companion.hasChild /** * @@ -18,7 +19,7 @@ import net.mamoe.mirai.console.permission.PermissibleIdentifier.Companion.grante @ExperimentalPermission internal abstract class AbstractConcurrentPermissionService

: PermissionService

{ protected abstract val permissions: MutableMap - protected abstract val grantedPermissionsMap: PluginDataExtensions.NotNullMutableMap> + protected abstract val grantedPermissionsMap: PluginDataExtensions.NotNullMutableMap> protected abstract fun createPermission( id: PermissionId, @@ -31,26 +32,28 @@ internal abstract class AbstractConcurrentPermissionService

: Pe override fun register(id: PermissionId, description: String, parent: Permission): P { val instance = createPermission(id, description, parent) val old = permissions.putIfAbsent(id, instance) - if (old != null) throw DuplicatedPermissionRegistrationException(instance, old) + if (old != null) throw PermissionRegistryConflictException(instance, old) return instance } - override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: P) { + override fun permit(permitteeId: PermitteeId, permission: P) { val id = permission.id - grantedPermissionsMap[id].add(permissibleIdentifier) + grantedPermissionsMap[id].add(permitteeId) } - override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: P) { - grantedPermissionsMap[permission.id].remove(permissibleIdentifier) + override fun cancel(permitteeId: PermitteeId, permission: P, recursive: Boolean) { + if (recursive) { + grantedPermissionsMap[permission.id] + } else grantedPermissionsMap[permission.id].remove(permitteeId) } override fun getRegisteredPermissions(): Sequence

= permissions.values.asSequence() - override fun getGrantedPermissions(permissibleIdentifier: PermissibleIdentifier): Sequence

= sequence

{ + override fun getPermittedPermissions(permitteeId: PermitteeId): Sequence

= sequence

{ for ((permissionIdentifier, permissibleIdentifiers) in grantedPermissionsMap) { val granted = if (permissibleIdentifiers.isEmpty()) false - else permissibleIdentifiers.any { permissibleIdentifier.grantedWith(it) } + else permissibleIdentifiers.any { permitteeId.hasChild(it) } if (granted) get(permissionIdentifier)?.let { yield(it) } } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/BuiltInPermissionServices.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/BuiltInPermissionServices.kt similarity index 72% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/BuiltInPermissionServices.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/BuiltInPermissionServices.kt index c1c3918e2..a49fcfdb2 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/BuiltInPermissionServices.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/BuiltInPermissionServices.kt @@ -7,20 +7,33 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -package net.mamoe.mirai.console.permission +package net.mamoe.mirai.console.internal.permission import kotlinx.serialization.Serializable import net.mamoe.mirai.console.data.AutoSavePluginConfig import net.mamoe.mirai.console.data.PluginDataExtensions import net.mamoe.mirai.console.data.PluginDataExtensions.withDefault import net.mamoe.mirai.console.data.value +import net.mamoe.mirai.console.permission.* import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.CopyOnWriteArraySet import kotlin.reflect.KClass +import kotlin.reflect.full.isSuperclassOf +@Suppress("unused") // don't pollute top-level +@OptIn(ExperimentalPermission::class) +internal fun PermissionService<*>.checkType(permissionType: KClass): PermissionService { + require(this.permissionType.isSuperclassOf(permissionType)) { + "Custom-constructed Permission instance is not allowed (Required ${this.permissionType}, found ${permissionType}. " + + "Please obtain Permission from PermissionService.INSTANCE.register or PermissionService.INSTANCE.get" + } + + @Suppress("UNCHECKED_CAST") + return this as PermissionService +} @ExperimentalPermission -internal object AllGrantPermissionService : PermissionService { +internal object AllPermitPermissionService : PermissionService { private val all = ConcurrentHashMap() override val permissionType: KClass get() = PermissionImpl::class override val rootPermission: PermissionImpl get() = RootPermissionImpl.also { all[it.id] = it } @@ -28,26 +41,26 @@ internal object AllGrantPermissionService : PermissionService { override fun register( id: PermissionId, description: String, - parent: Permission + parent: Permission, ): PermissionImpl { val new = PermissionImpl(id, description, parent) val old = all.putIfAbsent(id, new) - if (old != null) throw DuplicatedPermissionRegistrationException(new, old) + if (old != null) throw PermissionRegistryConflictException(new, old) return new } override fun get(id: PermissionId): PermissionImpl? = all[id] override fun getRegisteredPermissions(): Sequence = all.values.asSequence() - override fun getGrantedPermissions(permissibleIdentifier: PermissibleIdentifier): Sequence = + override fun getPermittedPermissions(permitteeId: PermitteeId): Sequence = all.values.asSequence() - override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { + override fun permit(permitteeId: PermitteeId, permission: PermissionImpl) { } - override fun testPermission(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl): Boolean = + override fun testPermission(permitteeId: PermitteeId, permission: PermissionImpl): Boolean = true - override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { + override fun cancel(permitteeId: PermitteeId, permission: PermissionImpl, recursive: Boolean) { } } @@ -65,26 +78,26 @@ internal object AllDenyPermissionService : PermissionService { override fun register( id: PermissionId, description: String, - parent: Permission + parent: Permission, ): PermissionImpl { val new = PermissionImpl(id, description, parent) val old = all.putIfAbsent(id, new) - if (old != null) throw DuplicatedPermissionRegistrationException(new, old) + if (old != null) throw PermissionRegistryConflictException(new, old) return new } override fun get(id: PermissionId): PermissionImpl? = all[id] override fun getRegisteredPermissions(): Sequence = all.values.asSequence() - override fun getGrantedPermissions(permissibleIdentifier: PermissibleIdentifier): Sequence = + override fun getPermittedPermissions(permitteeId: PermitteeId): Sequence = emptySequence() - override fun grant(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { + override fun permit(permitteeId: PermitteeId, permission: PermissionImpl) { } - override fun testPermission(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl): Boolean = + override fun testPermission(permitteeId: PermitteeId, permission: PermissionImpl): Boolean = false - override fun deny(permissibleIdentifier: PermissibleIdentifier, permission: PermissionImpl) { + override fun cancel(permitteeId: PermitteeId, permission: PermissionImpl, recursive: Boolean) { } } @@ -99,8 +112,8 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService

> - get() = config.grantedPermissionMap as PluginDataExtensions.NotNullMutableMap> + override val grantedPermissionsMap: PluginDataExtensions.NotNullMutableMap> + get() = config.grantedPermissionMap as PluginDataExtensions.NotNullMutableMap> override fun createPermission(id: PermissionId, description: String, parent: Permission): PermissionImpl = PermissionImpl(id, description, parent) @@ -112,10 +125,10 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService

> - by value>>(ConcurrentHashMap()) + public val grantedPermissionMap: PluginDataExtensions.NotNullMutableMap> + by value>>(ConcurrentHashMap()) .withDefault { CopyOnWriteArraySet() } public companion object { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/parseFromStringImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/parseFromStringImpl.kt new file mode 100644 index 000000000..6cc91ca49 --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/parseFromStringImpl.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2019-2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +@file:Suppress("unused") + +package net.mamoe.mirai.console.internal.permission + +import net.mamoe.mirai.console.permission.AbstractPermitteeId +import net.mamoe.mirai.console.permission.AbstractPermitteeId.* +import net.mamoe.mirai.console.permission.ExperimentalPermission + +@OptIn(ExperimentalPermission::class) +internal fun parseFromStringImpl(string: String): AbstractPermitteeId { + val str = string.trim { it.isWhitespace() }.toLowerCase() + if (str == "console") return Console + if (str.isNotEmpty()) { + when (str[0]) { + 'g' -> { + val arg = str.substring(1) + if (arg == "*") return AnyGroup + else arg.toLongOrNull()?.let(::ExactGroup)?.let { return it } + } + 'f' -> { + val arg = str.substring(1) + if (arg == "*") return AnyFriend + else arg.toLongOrNull()?.let(::ExactFriend)?.let { return it } + } + 'u' -> { + val arg = str.substring(1) + if (arg == "*") return AnyUser + else arg.toLongOrNull()?.let(::ExactUser)?.let { return it } + } + 'c' -> { + val arg = str.substring(1) + if (arg == "*") return AnyContact + } + 'm' -> kotlin.run { + val arg = str.substring(1) + if (arg == "*") return AnyMemberFromAnyGroup + else { + val components = arg.split('.') + + if (components.size == 2) { + val groupId = components[0].toLongOrNull() ?: return@run + + if (components[1] == "*") return AnyMember(groupId) + else { + val memberId = components[1].toLongOrNull() ?: return@run + return ExactMember(groupId, memberId) + } + } + } + } + 't' -> kotlin.run { + val arg = str.substring(1) + if (arg == "*") return AnyTempFromAnyGroup + else { + val components = arg.split('.') + + if (components.size == 2) { + val groupId = components[0].toLongOrNull() ?: return@run + + if (components[1] == "*") return AnyTemp(groupId) + else { + val memberId = components[1].toLongOrNull() ?: return@run + return ExactTemp(groupId, memberId) + } + } + } + } + } + } + error("Cannot deserialize '$str' as AbstractPermissibleIdentifier") +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/CommonUtils.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/CommonUtils.kt new file mode 100644 index 000000000..516609400 --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/util/CommonUtils.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +@file:JvmName("CommonUtils") + +package net.mamoe.mirai.console.internal.util + +internal inline fun runIgnoreException(block: () -> R): R? { + try { + return block() + } catch (e: Throwable) { + if (e is E) return null + throw e + } +} + +internal inline fun runIgnoreException(block: () -> Unit): Unit? { + try { + return block() + } catch (e: Throwable) { + if (e is E) return null + throw e + } +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt deleted file mode 100644 index 515b59164..000000000 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissibleIdentifier.kt +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -@file:Suppress("unused") - -package net.mamoe.mirai.console.permission - -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.builtins.serializer -import net.mamoe.mirai.console.internal.data.map -import net.mamoe.mirai.console.util.ConsoleExperimentalApi - -/** - */ -@ExperimentalPermission("Classname is subject to change") -public interface PermissibleIdentifier { - public val parents: Array - - public companion object { - @ExperimentalPermission - public fun PermissibleIdentifier.grantedWith(with: PermissibleIdentifier): Boolean { - return allParentsWithSelf().any { it == with } - } - - private fun PermissibleIdentifier.allParentsWithSelf(): Sequence { - return sequence { - yield(this@allParentsWithSelf) - yieldAll(parents.asSequence().flatMap { it.allParentsWithSelf() }) - } - } - } -} - -@Serializable(with = AbstractPermissibleIdentifier.AsStringSerializer::class) -@ExperimentalPermission -public sealed class AbstractPermissibleIdentifier( - public final override vararg val parents: PermissibleIdentifier -) : PermissibleIdentifier { - public companion object { - @JvmStatic - public fun parseFromString(string: String): AbstractPermissibleIdentifier { - val str = string.trim { it.isWhitespace() }.toLowerCase() - if (str == "console") return Console - if (str.isNotEmpty()) { - when (str[0]) { - 'g' -> { - val arg = str.substring(1) - if (arg == "*") return AnyGroup - else arg.toLongOrNull()?.let(::ExactGroup)?.let { return it } - } - 'f' -> { - val arg = str.substring(1) - if (arg == "*") return AnyFriend - else arg.toLongOrNull()?.let(::ExactFriend)?.let { return it } - } - 'u' -> { - val arg = str.substring(1) - if (arg == "*") return AnyUser - else arg.toLongOrNull()?.let(::ExactUser)?.let { return it } - } - 'c' -> { - val arg = str.substring(1) - if (arg == "*") return AnyContact - } - 'm' -> kotlin.run { - val arg = str.substring(1) - if (arg == "*") return AnyMemberFromAnyGroup - else { - val components = arg.split('.') - - if (components.size == 2) { - val groupId = components[0].toLongOrNull() ?: return@run - - if (components[1] == "*") return AnyMember(groupId) - else { - val memberId = components[1].toLongOrNull() ?: return@run - return ExactMember(groupId, memberId) - } - } - } - } - 't' -> kotlin.run { - val arg = str.substring(1) - if (arg == "*") return AnyTempFromAnyGroup - else { - val components = arg.split('.') - - if (components.size == 2) { - val groupId = components[0].toLongOrNull() ?: return@run - - if (components[1] == "*") return AnyTemp(groupId) - else { - val memberId = components[1].toLongOrNull() ?: return@run - return ExactTemp(groupId, memberId) - } - } - } - } - } - } - error("Cannot deserialize '$str' as AbstractPermissibleIdentifier") - } - } - - @ConsoleExperimentalApi - public object AsStringSerializer : KSerializer by String.serializer().map( - serializer = { it.toString() }, - - deserializer = d@{ str -> parseFromString(str) } - ) - - public object AnyGroup : AbstractPermissibleIdentifier(AnyContact) { - override fun toString(): String = "g*" - } - - public data class ExactGroup(public val groupId: Long) : AbstractPermissibleIdentifier(AnyGroup) { - override fun toString(): String = "g$groupId" - } - - public data class AnyMember(public val groupId: Long) : AbstractPermissibleIdentifier(AnyMemberFromAnyGroup) { - override fun toString(): String = "m$groupId.*" - } - - public object AnyMemberFromAnyGroup : AbstractPermissibleIdentifier(AnyUser) { - override fun toString(): String = "m*" - } - - public object AnyTempFromAnyGroup : AbstractPermissibleIdentifier(AnyUser) { - override fun toString(): String = "t*" - } - - public data class ExactMember( - public val groupId: Long, - public val memberId: Long - ) : AbstractPermissibleIdentifier(AnyMember(groupId), ExactUser(memberId)) { - override fun toString(): String = "m$groupId.$memberId" - } - - public object AnyFriend : AbstractPermissibleIdentifier(AnyUser) { - override fun toString(): String = "f*" - } - - public data class ExactFriend( - public val id: Long - ) : AbstractPermissibleIdentifier(ExactUser(id)) { - override fun toString(): String = "f$id" - } - - public data class AnyTemp( - public val groupId: Long, - ) : AbstractPermissibleIdentifier(AnyUser, AnyMember(groupId)) { - override fun toString(): String = "t$groupId.*" - } - - public data class ExactTemp( - public val groupId: Long, - public val memberId: Long - ) : AbstractPermissibleIdentifier(ExactUser(groupId), ExactMember(groupId, memberId)) { - override fun toString(): String = "t$groupId.$memberId" - } - - public object AnyUser : AbstractPermissibleIdentifier(AnyContact) { - override fun toString(): String = "u*" - } - - public data class ExactUser( - public val id: Long - ) : AbstractPermissibleIdentifier(AnyUser) { - override fun toString(): String = "u$id" - } - - public object AnyContact : AbstractPermissibleIdentifier() { - override fun toString(): String = "*" - } - - public object Console : AbstractPermissibleIdentifier() { - override fun toString(): String = "console" - } -} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt index e251b77de..be88bbd34 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt @@ -9,49 +9,75 @@ package net.mamoe.mirai.console.permission -import net.mamoe.mirai.console.util.ConsoleExperimentalApi - +import net.mamoe.mirai.console.command.BuiltInCommands +import net.mamoe.mirai.console.command.Command /** - * 一个权限节点. + * 一个权限. * * 由 [PermissionService] 实现不同, [Permission] 可能会有多种实例. 但一个权限总是拥有确定的 [id]. * - * 请不要手动实现这个接口. 总是从 [PermissionService.register] 获得实例. + * **注意**: 请不要手动实现这个接口. 总是从 [PermissionService.register] 获得实例. + * + * ### 获取 [Permission] + * + * #### 根权限 + * [RootPermission] 是所有权限的父权限. + * + * #### 指令的权限 + * 每个指令都拥有一个 [Command.permission]. + * + * [BuiltInCommands.rootPermission] 为所有内建指令的权限. + * + * #### 手动申请权限 + * [PermissionService.register] */ -@ExperimentalPermission public interface Permission { + /** + * 唯一识别 ID. 所有权限的 [id] 都互不相同. + * + * @see PermissionService.get 由 [id] 获取已注册的 [Permission] + * @see PermissionId + */ public val id: PermissionId + + /** + * 描述信息. 描述信息在注册权限时强制提供. + */ public val description: String /** + * 父权限. + * * [RootPermission] 的 parent 为自身 */ public val parent: Permission + + public companion object { + /** + * 根权限. 是所有权限的父权限. + * + * 供 Java 用户使用. + * + * @see RootPermission 推荐 Kotlin 用户使用. + */ + @JvmStatic + public fun getRootPermission(): Permission = PermissionService.INSTANCE.rootPermission + + /** + * 递归获取 [Permission.parent], `permission.parent.parent`, permission.parent.parent` ... 直到 [Permission.parent] 为它自己. + */ + @get:JvmStatic + public val Permission.parentsWithSelf: Sequence + get() = generateSequence(this) { p -> + p.parent.takeIf { parent -> parent != p } + } + } } /** - * 所有权限的父权限. + * 根权限. 是所有权限的父权限. */ -@get:JvmName("getRootPermission") -@ExperimentalPermission +@get:JvmSynthetic public val RootPermission: Permission - get() = PermissionService.INSTANCE.rootPermission - -/** - * 所有内建指令的权限 - */ -@ExperimentalPermission -public val RootConsoleBuiltInPermission: Permission by lazy { - PermissionService.INSTANCE.register( - PermissionId("console", "*"), - "The parent of any built-in commands" - ) -} - -@ConsoleExperimentalApi -@ExperimentalPermission -public fun Permission.parentsWithSelfSequence(): Sequence = - generateSequence(this) { p -> - p.parent.takeIf { parent -> parent != p } - } \ No newline at end of file + get() = PermissionService.INSTANCE.rootPermission \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt index d4362a5ae..caabfd017 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionId.kt @@ -11,19 +11,19 @@ package net.mamoe.mirai.console.permission import kotlinx.serialization.KSerializer import kotlinx.serialization.Serializable -import kotlinx.serialization.Serializer import kotlinx.serialization.builtins.serializer import net.mamoe.mirai.console.internal.data.map /** + * 表示一个 [权限][Permission] 的唯一 ID. + * * [PermissionId] 与 [Permission] 唯一对应. */ -@Serializable(with = PermissionId.AsStringSerializer::class) -@ExperimentalPermission +@Serializable(with = PermissionId.PermissionIdAsStringSerializer::class) public data class PermissionId( public val namespace: String, - public val id: String + public val id: String, ) { init { require(!namespace.contains(':')) { @@ -34,21 +34,30 @@ public data class PermissionId( } } - @Serializer(forClass = PermissionId::class) - public object AsClassSerializer - - public object AsStringSerializer : KSerializer by String.serializer().map( + public object PermissionIdAsStringSerializer : KSerializer by String.serializer().map( serializer = { it.namespace + ":" + it.id }, deserializer = { it.split(':').let { (namespace, id) -> PermissionId(namespace, id) } } ) - public override fun toString(): String { - return "$namespace:$id" - } + /** + * 返回 `$namespace:$id` + */ + public override fun toString(): String = "$namespace:$id" public companion object { - public fun parseFromString(string: String): PermissionId = - string.split(':').let { (namespace, id) -> PermissionId(namespace, id) } + /** + * 由 `$namespace:$id` 解析 [PermissionId]. + * + * @throws IllegalArgumentException 在解析失败时抛出. + */ + @JvmStatic + public fun parseFromString(string: String): PermissionId { + return kotlin.runCatching { + string.split(':').let { (namespace, id) -> PermissionId(namespace, id) } + }.getOrElse { + throw IllegalArgumentException("Could not parse PermissionId from '$string'", it) + } + } } } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt index 6ce0a93a5..305369090 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt @@ -9,8 +9,6 @@ package net.mamoe.mirai.console.permission -@ExperimentalPermission public interface PermissionIdNamespace { - @ExperimentalPermission public fun permissionId(id: String): PermissionId } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionImplementation.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionImplementation.kt new file mode 100644 index 000000000..ddedd80d7 --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionImplementation.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +package net.mamoe.mirai.console.permission + +import kotlin.annotation.AnnotationTarget.* + +/** + * 表示一个应该由 [权限服务][PermissionService] 实现的类. + * + * 这样的类不能被用户手动实现或者继承, 也不能使用属性委托或者类委托, 或者其他任意改变实现类的手段. + * 用户仅应该使用从 [PermissionService] 或其他途径获取这些对象, 而不能自行实现它们. + */ +@Retention(AnnotationRetention.BINARY) +@Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR) +@MustBeDocumented +internal annotation class PermissionImplementation \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionNotFoundException.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionNotFoundException.kt deleted file mode 100644 index e005fd0aa..000000000 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionNotFoundException.kt +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.console.permission - -@ExperimentalPermission -public open class PermissionNotFoundException public constructor( - public val id: PermissionId -) : Exception(id.toString()) \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/DuplicatedPermissionRegistrationException.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionRegistryConflictException.kt similarity index 68% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/DuplicatedPermissionRegistrationException.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionRegistryConflictException.kt index 39cbb2807..de85ebe53 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/DuplicatedPermissionRegistrationException.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionRegistryConflictException.kt @@ -11,8 +11,10 @@ package net.mamoe.mirai.console.permission -@ExperimentalPermission -public class DuplicatedPermissionRegistrationException( - newInstance: Permission, - public val existingInstance: Permission -) : Exception("Duplicated Permission registry. new: $newInstance, existing: $existingInstance") \ No newline at end of file +/** + * @see PermissionService.register + */ +public class PermissionRegistryConflictException( + public val newInstance: Permission, + public val existingInstance: Permission, +) : Exception("Conflicted Permission registry. new: $newInstance, existing: $existingInstance") \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt index cef6b07de..787792e09 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionService.kt @@ -12,13 +12,18 @@ package net.mamoe.mirai.console.permission import net.mamoe.mirai.console.extensions.PermissionServiceProvider +import net.mamoe.mirai.console.internal.permission.checkType +import net.mamoe.mirai.console.permission.Permission.Companion.parentsWithSelf import kotlin.reflect.KClass -import kotlin.reflect.full.isSuperclassOf /** + * 权限服务. 用于承载 Console 的权限系统. + * + * ### 可扩展 + * 权限服务可由插件扩展并覆盖默认实现. + * * [PermissionServiceProvider] */ -@ExperimentalPermission public interface PermissionService

{ @ExperimentalPermission public val permissionType: KClass

@@ -29,12 +34,25 @@ public interface PermissionService

{ public operator fun get(id: PermissionId): P? public fun getRegisteredPermissions(): Sequence

- public fun getGrantedPermissions(permissibleIdentifier: PermissibleIdentifier): Sequence

- public fun testPermission(permissibleIdentifier: PermissibleIdentifier, permission: P): Boolean { + /** + * 获取 [PermitteeId] 和其父标识的所有被授予的所有直接和间接的权限列表 + */ + public fun getPermittedPermissions(permitteeId: PermitteeId): Sequence

+ + /** + * 判断 [permission] 对 [permission] 的权限. + * + * 返回 `true` 的意义: + * - 通常意义: [permitteeId] 拥有 [permission] 的 '能力' + * - 实现意义: [permitteeId] 自身或任意父标识 [PermissionService] 被授予高于或等于 [permission] 的权限 + * + * @see Companion.testPermission 接收 [Permittee] 参数的扩展 + */ + public fun testPermission(permitteeId: PermitteeId, permission: P): Boolean { val permissionId = permission.id - val all = this[permissionId]?.parentsWithSelfSequence() ?: return false - return getGrantedPermissions(permissibleIdentifier).any { p -> + val all = this[permissionId]?.parentsWithSelf ?: return false + return getPermittedPermissions(permitteeId).any { p -> all.any { p.id == it.id } } } @@ -42,7 +60,12 @@ public interface PermissionService

{ /////////////////////////////////////////////////////////////////////////// - @Throws(DuplicatedPermissionRegistrationException::class) + /** + * 申请并注册一个权限 [Permission]. + * + * @throws PermissionRegistryConflictException 当已存在一个 [PermissionId] 时抛出. + */ + @Throws(PermissionRegistryConflictException::class) public fun register( id: PermissionId, description: String, @@ -51,8 +74,28 @@ public interface PermissionService

{ /////////////////////////////////////////////////////////////////////////// - public fun grant(permissibleIdentifier: PermissibleIdentifier, permission: P) - public fun deny(permissibleIdentifier: PermissibleIdentifier, permission: P) + /** + * 授予 [permitteeId] 以 [permission] 权限 + * + * Console 内建的权限服务支持授予操作. 但插件扩展的权限服务可能不支持. + * + * @throws UnsupportedOperationException 当插件扩展的 [PermissionService] 不支持这样的操作时抛出. + */ + public fun permit(permitteeId: PermitteeId, permission: P) + + /** + * 撤销 [permitteeId] 的 [permission] 授权 + * + * Console 内建的权限服务支持授予操作. 但插件扩展的权限服务可能不支持. + * + * @param recursive `true` 时递归撤销所有子权限. + * 例如, 若 [permission] 为 "*:*", + * recursive 为 `true` 时撤销全部权限 (因为所有权限都是 "*:*" 的子权限); + * 而为 `false` 时仅撤销 "*:*" 本身, 而不会影响子权限. + * + * @throws UnsupportedOperationException 当插件扩展的 [PermissionService] 不支持这样的操作时抛出. + */ + public fun cancel(permitteeId: PermitteeId, permission: P, recursive: Boolean) public companion object { internal var instanceField: PermissionService<*>? = null @@ -63,7 +106,7 @@ public interface PermissionService

{ get() = instanceField ?: error("PermissionService is not yet initialized therefore cannot be used.") public fun

PermissionService

.getOrFail(id: PermissionId): P = - get(id) ?: throw PermissionNotFoundException(id) + get(id) ?: throw NoSuchElementException("Permission not found: $id") internal fun PermissionService<*>.allocatePermissionIdForPlugin(name: String, id: String) = PermissionId("plugin.${name.toLowerCase()}", id.toLowerCase()) @@ -72,81 +115,68 @@ public interface PermissionService

{ public fun PermissionId.findCorrespondingPermissionOrFail(): Permission = INSTANCE.getOrFail(this) - public fun PermissibleIdentifier.grantPermission(permission: Permission) { - INSTANCE.checkType(permission::class).grant(this, permission) + public fun PermitteeId.grantPermission(permission: Permission) { + INSTANCE.checkType(permission::class).permit(this, permission) } - public fun PermissibleIdentifier.grantPermission(permissionId: PermissionId) { + public fun PermitteeId.grantPermission(permissionId: PermissionId) { grantPermission(permissionId.findCorrespondingPermissionOrFail()) } - public fun PermissibleIdentifier.denyPermission(permission: Permission) { - INSTANCE.checkType(permission::class).deny(this, permission) + public fun PermitteeId.denyPermission(permission: Permission, recursive: Boolean) { + INSTANCE.checkType(permission::class).cancel(this, permission, recursive) } - public fun PermissibleIdentifier.denyPermission(permissionId: PermissionId) { - denyPermission(permissionId.findCorrespondingPermissionOrFail()) + public fun PermitteeId.denyPermission(permissionId: PermissionId, recursive: Boolean) { + denyPermission(permissionId.findCorrespondingPermissionOrFail(), recursive) } - public fun Permissible.hasPermission(permission: Permission): Boolean = + public fun Permittee.hasPermission(permission: Permission): Boolean = permission.testPermission(this@hasPermission) - public fun PermissibleIdentifier.hasPermission(permission: Permission): Boolean = + public fun PermitteeId.hasPermission(permission: Permission): Boolean = permission.testPermission(this@hasPermission) - public fun PermissibleIdentifier.hasPermission(permissionId: PermissionId): Boolean { + public fun PermitteeId.hasPermission(permissionId: PermissionId): Boolean { val instance = permissionId.findCorrespondingPermissionOrFail() return INSTANCE.checkType(instance::class).testPermission(this@hasPermission, instance) } - public fun Permissible.hasPermission(permissionId: PermissionId): Boolean = + public fun Permittee.hasPermission(permissionId: PermissionId): Boolean = permissionId.testPermission(this@hasPermission) - public fun Permissible.getGrantedPermissions(): Sequence = - INSTANCE.getGrantedPermissions(this@getGrantedPermissions.identifier) + public fun Permittee.getPermittedPermissions(): Sequence = + INSTANCE.getPermittedPermissions(this@getPermittedPermissions.permitteeId) - public fun Permissible.grantPermission(vararg permissions: Permission) { + public fun Permittee.grantPermission(vararg permissions: Permission) { for (permission in permissions) { - INSTANCE.checkType(permission::class).grant(this.identifier, permission) + INSTANCE.checkType(permission::class).permit(this.permitteeId, permission) } } - public fun Permissible.denyPermission(vararg permissions: Permission) { + public fun Permittee.denyPermission(vararg permissions: Permission, recursive: Boolean) { for (permission in permissions) { - INSTANCE.checkType(permission::class).deny(this.identifier, permission) + INSTANCE.checkType(permission::class).cancel(this.permitteeId, permission, recursive) } } - public fun PermissibleIdentifier.getGrantedPermissions(): Sequence = - INSTANCE.getGrantedPermissions(this@getGrantedPermissions) + public fun PermitteeId.getPermittedPermissions(): Sequence = + INSTANCE.getPermittedPermissions(this@getPermittedPermissions) - public fun Permission.testPermission(permissible: Permissible): Boolean = - INSTANCE.checkType(this::class).testPermission(permissible.identifier, this@testPermission) + public fun Permission.testPermission(permittee: Permittee): Boolean = + INSTANCE.checkType(this::class).testPermission(permittee.permitteeId, this@testPermission) - public fun Permission.testPermission(permissibleIdentifier: PermissibleIdentifier): Boolean = - INSTANCE.checkType(this::class).testPermission(permissibleIdentifier, this@testPermission) + public fun Permission.testPermission(permitteeId: PermitteeId): Boolean = + INSTANCE.checkType(this::class).testPermission(permitteeId, this@testPermission) - public fun PermissionId.testPermission(permissible: Permissible): Boolean { + public fun PermissionId.testPermission(permittee: Permittee): Boolean { val p = INSTANCE[this] ?: return false - return p.testPermission(permissible) + return p.testPermission(permittee) } - public fun PermissionId.testPermission(permissible: PermissibleIdentifier): Boolean { + public fun PermissionId.testPermission(permissible: PermitteeId): Boolean { val p = INSTANCE[this] ?: return false return p.testPermission(permissible) } } -} - -@OptIn(ExperimentalPermission::class) -internal fun PermissionService<*>.checkType(permissionType: KClass): PermissionService { - return PermissionService.INSTANCE.run { - require(this.permissionType.isSuperclassOf(permissionType)) { - "Custom-constructed Permission instance is not allowed (Required ${this.permissionType}, found ${permissionType}. " + - "Please obtain Permission from PermissionService.INSTANCE.register or PermissionService.INSTANCE.get" - } - - @Suppress("UNCHECKED_CAST") - this as PermissionService - } -} +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permissible.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permittee.kt similarity index 62% rename from backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permissible.kt rename to backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permittee.kt index b970e50e5..e7235e22a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permissible.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permittee.kt @@ -14,15 +14,15 @@ package net.mamoe.mirai.console.permission import net.mamoe.mirai.console.command.CommandSender /** - * 可拥有权限的对象. + * 可被赋予权限的对象, 即 '被许可人'. * - * 典型的实例为 [CommandSender] + * 被许可人自身不持有拥有的权限列表, 而是拥有 [PermitteeId], 标识自己的身份, 供 [权限服务][PermissionService] 处理. * - * 注意: 请不要自主实现 [Permissible] + * **注意**: 请不要自主实现 [Permittee] * * @see CommandSender */ -@ExperimentalPermission -public interface Permissible { - public val identifier: PermissibleIdentifier +@PermissionImplementation +public interface Permittee { + public val permitteeId: PermitteeId } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermitteeId.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermitteeId.kt new file mode 100644 index 000000000..da363b47f --- /dev/null +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermitteeId.kt @@ -0,0 +1,307 @@ +/* + * Copyright 2019-2020 Mamoe Technologies and contributors. + * + * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. + * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. + * + * https://github.com/mamoe/mirai/blob/master/LICENSE + */ + +@file:Suppress("unused") + +package net.mamoe.mirai.console.permission + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.serializer +import net.mamoe.mirai.console.internal.data.map +import net.mamoe.mirai.console.internal.permission.parseFromStringImpl +import net.mamoe.mirai.console.permission.AbstractPermitteeId.AnyMember +import net.mamoe.mirai.console.permission.AbstractPermitteeId.ExactMember +import net.mamoe.mirai.console.util.ConsoleExperimentalApi +import net.mamoe.mirai.contact.Contact +import net.mamoe.mirai.contact.Member +import net.mamoe.mirai.contact.User + +/** + * [被许可人][Permittee] 的标识符 + * + * 一个这样的标识符即可代表特定的单个 [Permittee], 也可以表示多个同类 [Permittee]. + * + * ### 获取 [PermitteeId] + * 总是通过 [Permittee.permitteeId]. + */ +@PermissionImplementation +public interface PermitteeId { + /** + * 直接父 [PermitteeId]. 在检查权限时会首先检查自己, 再递归检查父类. + * + * @see allParentsWithSelf + * @see allParents + */ + public val directParents: Array + + /** + * 转换为字符串表示. 用于权限服务识别和指令的解析. + */ + public fun asString(): String + + public companion object { + /** + * 当 [this] 或 [this] 的任意一个直接或间接父 [PermitteeId.asString] 与 `this.asString` 相同时返回 `true` + */ + @JvmStatic + public fun PermitteeId.hasChild(child: PermitteeId): Boolean { + return allParentsWithSelf.any { it.asString() == child.asString() } // asString is for compatibility issue with external implementations + } + + /** + * 获取所有直接或间接父类的 [PermitteeId]. + */ + @get:JvmStatic + public val PermitteeId.allParentsWithSelf: Sequence + get() = sequence { + yield(this@allParentsWithSelf) + yieldAll(allParents) + } + + /** + * 获取所有直接或间接父类的 [PermitteeId], 返回包含 `this` + 这些父类 的 [Sequence] + */ + @get:JvmStatic + public val PermitteeId.allParents: Sequence + get() = directParents.asSequence().flatMap { it.allParentsWithSelf } + } +} + +/** + * 内建的 [PermitteeId]. + * + * - 若指令 A 的权限被授予给 [AnyMember], 那么一个 [ExactMember] 可以执行这个指令. + * + * ``` + * Console AnyContact + * ↑ + * | + * +---------------------------+------------------------+ + * | | + * AnyUser AnyGroup + * ↑ ↑ + * | | + * +--------------+---------------------+ | + * | | | | + * AnyFriend | AnyMemberFromAnyGroup | + * ↑ | ↑ | + * | | | | + * | | +--------+--------------+ | + * | | | | | + * | | | AnyTempFromAnyGroup | + * | | | ↑ | + * | | AnyMember | | + * | | ↑ | | + * | ExactUser | | ExactGroup + * | ↑ ↑ | | + * | | | | | + * +------------+ +----------+ | + * | | | + * ExactFriend ExactMember | + * ↑ | + * | | + * +-----------------------+ + * | + * | + * ExactTemp + * ``` + */ +@Serializable(with = AbstractPermitteeId.AsStringSerializer::class) +public sealed class AbstractPermitteeId( + public final override vararg val directParents: PermitteeId, +) : PermitteeId { + public final override fun toString(): String = asString() + + public companion object { + /** + * 由 [AbstractPermitteeId.asString] 解析 [AbstractPermitteeId] + */ + @JvmStatic + public fun parseFromString(string: String): AbstractPermitteeId = parseFromStringImpl(string) + } + + /** + * 使用 [asString] 序列化 [AbstractPermitteeId] + */ + @ConsoleExperimentalApi + public object AsStringSerializer : KSerializer by String.serializer().map( + serializer = AbstractPermitteeId::asString, + deserializer = ::parseFromString + ) + + /** + * 表示任何群对象. (不是指群成员, 而是指这个 '群') + * + * - **直接父标识符**: [AnyContact] + * - **间接父标识符**: 无 + * - 字符串表示: "g*" + * + * @see AnyMember + */ + public object AnyGroup : AbstractPermitteeId(AnyContact) { + override fun asString(): String = "g*" + } + + /** + * 表示一个群 + * + * - **直接父标识符**: [AnyGroup] + * - **间接父标识符**: [AnyContact] + * - 字符串表示: "g$groupId" + */ + public data class ExactGroup(public val groupId: Long) : AbstractPermitteeId(AnyGroup) { + override fun asString(): String = "g$groupId" + } + + /** + * 表示来自一个群的任意一个成员 + * + * - **直接父标识符**: [AnyMemberFromAnyGroup] + * - **间接父标识符**: [AnyUser], [AnyContact] + * - 字符串表示: "m$groupId.*" + */ + public data class AnyMember(public val groupId: Long) : AbstractPermitteeId(AnyMemberFromAnyGroup) { + override fun asString(): String = "m$groupId.*" + } + + /** + * 表示来自任意群的任意一个成员 + * + * - **直接父标识符**: [AnyUser] + * - **间接父标识符**: [AnyContact] + * - 字符串表示: "m*" + */ + public object AnyMemberFromAnyGroup : AbstractPermitteeId(AnyUser) { + override fun asString(): String = "m*" + } + + /** + * 表示唯一的一个群成员 + * + * - **直接父标识符**: [AnyMember], [ExactUser] + * - **间接父标识符**: [AnyMemberFromAnyGroup], [AnyUser], [AnyContact] + * - 字符串表示: "m$groupId.$memberId" + */ + public data class ExactMember( + public val groupId: Long, + public val memberId: Long, + ) : AbstractPermitteeId(AnyMember(groupId), ExactUser(memberId)) { + override fun asString(): String = "m$groupId.$memberId" + } + + /** + * 表示任何好友 + * + * - **直接父标识符**: [AnyUser] + * - **间接父标识符**: [AnyContact] + * - 字符串表示: "f*" + */ + public object AnyFriend : AbstractPermitteeId(AnyUser) { + override fun asString(): String = "f*" + } + + /** + * 表示唯一的一个好友 + * + * - **直接父标识符**: [ExactUser] + * - **间接父标识符**: [AnyUser], [AnyContact] + * - 字符串表示: "f$id" + */ + public data class ExactFriend( + public val id: Long, + ) : AbstractPermitteeId(ExactUser(id)) { + override fun asString(): String = "f$id" + } + + /** + * 表示任何一个通过一个群 *在临时会话发送消息的* [群成员][Member] + * + * - **直接父标识符**: [AnyMember], [AnyTempFromAnyGroup] + * - **间接父标识符**: [AnyMemberFromAnyGroup], [AnyUser], [AnyContact] + * - 字符串表示: "t$groupId.*" + */ + public data class AnyTemp( + public val groupId: Long, + ) : AbstractPermitteeId(AnyMember(groupId), AnyTempFromAnyGroup) { + override fun asString(): String = "t$groupId.*" + } + + /** + * 表示任何一个 *在临时会话发送消息的* [群成员][Member] + * + * - **直接父标识符**: [AnyUser] + * - **间接父标识符**: [AnyContact] + * - 字符串表示: "t*" + */ + public object AnyTempFromAnyGroup : AbstractPermitteeId(AnyUser) { + override fun asString(): String = "t*" + } + + /** + * 表示唯一的一个 *在临时会话发送消息的* [群成员][Member] + * + * - **直接父标识符**: [ExactMember] + * - **间接父标识符**: [AnyUser], [AnyMember], [ExactUser], [AnyContact] + * - 字符串表示: "t$groupId.$memberId" + */ + public data class ExactTemp( + public val groupId: Long, + public val memberId: Long, + ) : AbstractPermitteeId(ExactMember(groupId, memberId)) { + override fun asString(): String = "t$groupId.$memberId" + } + + + /** + * 表示任何 [用户][User] + * + * - **直接父标识符**: [AnyContact] + * - **间接父标识符**: 无 + * - 字符串表示: "u*" + */ + public object AnyUser : AbstractPermitteeId(AnyContact) { + override fun asString(): String = "u*" + } + + /** + * 表示任何 [用户][User] + * + * - **直接父标识符**: [AnyUser] + * - **间接父标识符**: [AnyContact] + * - 字符串表示: "u$id" + */ + public data class ExactUser( + public val id: Long, + ) : AbstractPermitteeId(AnyUser) { + override fun asString(): String = "u$id" + } + + /** + * 表示任何 [联系对象][Contact] + * + * - **直接父标识符**: 无 + * - **间接父标识符**: 无 + * - 字符串表示: "*" + */ + public object AnyContact : AbstractPermitteeId() { + override fun asString(): String = "*" + } + + /** + * 表示控制台 + * + * - **直接父标识符**: 无 + * - **间接父标识符**: 无 + * - 字符串表示: "console" + */ + public object Console : AbstractPermitteeId() { + override fun asString(): String = "console" + } +} \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt index 825d7b89a..9b3aef0ed 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/util/ContactUtils.kt @@ -12,8 +12,8 @@ package net.mamoe.mirai.console.util import net.mamoe.mirai.Bot -import net.mamoe.mirai.contact.Contact -import net.mamoe.mirai.contact.Member +import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip +import net.mamoe.mirai.contact.* /** * 为简化操作提供的一些工具 @@ -32,7 +32,7 @@ public object ContactUtils { @JvmOverloads @JvmStatic @ConsoleExperimentalApi - public fun Bot.getContact(id: Long, includeMembers: Boolean = false): Contact { + public fun Bot.getContact(id: Long, includeMembers: Boolean = true): Contact { return getContactOrNull(id, includeMembers) ?: throw NoSuchElementException("Contact $id not found for bot ${this.id}") } @@ -45,7 +45,7 @@ public object ContactUtils { @JvmOverloads @JvmStatic @ConsoleExperimentalApi - public fun Bot.getContactOrNull(id: Long, includeMembers: Boolean = false): Contact? { + public fun Bot.getContactOrNull(id: Long, includeMembers: Boolean = true): Contact? { return getFriendOrGroupOrNull(id) ?: kotlin.run { if (includeMembers) { groups.asSequence().flatMap { it.members.asSequence() }.firstOrNull { it.id == id } @@ -77,4 +77,18 @@ public object ContactUtils { return this.friends.getOrNull(id) ?: this.groups.getOrNull(id) } + /** + * 将 [ContactOrBot] 输出为字符串表示. + */ + @JvmName("renderContactOrName") + @JvmStatic + public fun ContactOrBot.render(): String { + return when (this) { + is Bot -> "Bot $nick($id)" + is Group -> "Group $name($id)" + is Friend -> "Friend $nick($id)" + is Member -> "Member $nameCardOrNick(${group.id}.$id)" + else -> error("Illegal type for ContactOrBot: ${this::class.qualifiedNameOrTip}") + } + } } \ No newline at end of file From 3a45254fee1deb9e01e2d27e10c889c0b6148d92 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 19:00:18 +0800 Subject: [PATCH 11/14] Rename BuiltInCommands.rootPermission to BuiltInCommands.parentPermission; Update docs --- .../mirai/console/command/BuiltInCommands.kt | 6 +----- .../mamoe/mirai/console/command/CommandOwner.kt | 17 +++++++---------- .../mirai/console/permission/Permission.kt | 2 +- .../console/permission/PermissionIdNamespace.kt | 6 ++++++ 4 files changed, 15 insertions(+), 16 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt index 827a216d8..fe39c5268 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt @@ -47,7 +47,7 @@ internal interface BuiltInCommandInternal : Command, BuiltInCommand @OptIn(ExperimentalPermission::class) public object BuiltInCommands { @ConsoleExperimentalApi - public val rootPermission: Permission by lazy { + public val parentPermission: Permission by lazy { PermissionService.INSTANCE.register( PermissionId("console", "*"), "The parent of any built-in commands" @@ -67,7 +67,6 @@ public object BuiltInCommands { public object HelpCommand : SimpleCommand( ConsoleCommandOwner, "help", description = "Command list", - parentPermission = rootPermission, ), BuiltInCommandInternal { @Handler public suspend fun CommandSender.handle() { @@ -87,7 +86,6 @@ public object BuiltInCommands { public object StopCommand : SimpleCommand( ConsoleCommandOwner, "stop", "shutdown", "exit", description = "Stop the whole world.", - parentPermission = rootPermission, ), BuiltInCommandInternal { private val closingLock = Mutex() @@ -123,7 +121,6 @@ public object BuiltInCommands { public object LoginCommand : SimpleCommand( ConsoleCommandOwner, "login", "登录", description = "Log in a bot account.", - parentPermission = rootPermission, ), BuiltInCommandInternal { @Handler public suspend fun CommandSender.handle(id: Long, password: String) { @@ -160,7 +157,6 @@ public object BuiltInCommands { }.getOrElse { illegalArgument("指令不存在: $id", it) } } }, - parentPermission = rootPermission, ), BuiltInCommandInternal { // TODO: 2020/9/10 improve Permission command @SubCommand("permit", "grant", "add") diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt index bbe1bd642..22a988511 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt @@ -10,11 +10,14 @@ package net.mamoe.mirai.console.command import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands -import net.mamoe.mirai.console.permission.* +import net.mamoe.mirai.console.permission.ExperimentalPermission +import net.mamoe.mirai.console.permission.Permission +import net.mamoe.mirai.console.permission.PermissionId +import net.mamoe.mirai.console.permission.PermissionIdNamespace import net.mamoe.mirai.console.plugin.jvm.JvmPlugin /** - * 指令的所有者. 目前仅作为标识作用. + * 指令的所有者. * * @see CommandManager.unregisterAllCommands 取消注册所有属于一个 [CommandOwner] 的指令 * @see CommandManager.registeredCommands 获取已经注册了的属于一个 [CommandOwner] 的指令列表. @@ -24,11 +27,8 @@ import net.mamoe.mirai.console.plugin.jvm.JvmPlugin @OptIn(ExperimentalPermission::class) public interface CommandOwner : PermissionIdNamespace { /** - * 此 [PermissionIdNamespace] 拥有的指令都默认将 [parentPermission] 作为父权限. - * - * TODO document + * 在构造指令时, [Command.permission] 默认会使用 [parentPermission] 作为 [Permission.parent] */ - @ExperimentalPermission public val parentPermission: Permission } @@ -36,10 +36,7 @@ public interface CommandOwner : PermissionIdNamespace { * 代表控制台所有者. 所有的 mirai-console 内建的指令都属于 [ConsoleCommandOwner]. */ internal object ConsoleCommandOwner : CommandOwner { - @ExperimentalPermission - override val parentPermission: Permission - get() = RootPermission + override val parentPermission: Permission get() = BuiltInCommands.parentPermission - @ExperimentalPermission override fun permissionId(id: String): PermissionId = PermissionId("console", id) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt index be88bbd34..963863be7 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/Permission.kt @@ -27,7 +27,7 @@ import net.mamoe.mirai.console.command.Command * #### 指令的权限 * 每个指令都拥有一个 [Command.permission]. * - * [BuiltInCommands.rootPermission] 为所有内建指令的权限. + * [BuiltInCommands.parentPermission] 为所有内建指令的权限. * * #### 手动申请权限 * [PermissionService.register] diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt index 305369090..60e47ff91 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/permission/PermissionIdNamespace.kt @@ -9,6 +9,12 @@ package net.mamoe.mirai.console.permission +/** + * [PermissionId] 的命名空间. 用于提供 [PermissionId.namespace]. + */ public interface PermissionIdNamespace { + /** + * 创建一个此命名空间下的 [PermitteeId] + */ public fun permissionId(id: String): PermissionId } \ No newline at end of file From 79136a26662084870c2abc314141b50ae4a28901 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 19:06:05 +0800 Subject: [PATCH 12/14] Add extensions for CommandSender.execute(Command,...) --- .../mirai/console/command/CommandManager.kt | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt index 6977582d5..a14c70c39 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandManager.kt @@ -104,7 +104,7 @@ public interface CommandManager { @JvmBlockingBridge public suspend fun CommandSender.executeCommand( message: Message, - checkPermission: Boolean = true + checkPermission: Boolean = true, ): CommandExecuteResult /** @@ -120,7 +120,7 @@ public interface CommandManager { @JvmBlockingBridge public suspend fun CommandSender.executeCommand( message: String, - checkPermission: Boolean = true + checkPermission: Boolean = true, ): CommandExecuteResult = executeCommand(PlainText(message).asMessageChain(), checkPermission) /** @@ -132,7 +132,7 @@ public interface CommandManager { public suspend fun Command.execute( sender: CommandSender, arguments: Message = EmptyMessageChain, - checkPermission: Boolean = true + checkPermission: Boolean = true, ): CommandExecuteResult /** @@ -145,7 +145,7 @@ public interface CommandManager { public suspend fun Command.execute( sender: CommandSender, arguments: String = "", - checkPermission: Boolean = true + checkPermission: Boolean = true, ): CommandExecuteResult = execute(sender, PlainText(arguments).asMessageChain(), checkPermission) public companion object INSTANCE : CommandManager by CommandManagerImpl { @@ -165,24 +165,48 @@ public interface CommandManager { override suspend fun Command.execute( sender: CommandSender, arguments: Message, - checkPermission: Boolean + checkPermission: Boolean, ): CommandExecuteResult = CommandManagerImpl.run { execute(sender, arguments = arguments, checkPermission = checkPermission) } override suspend fun CommandSender.executeCommand( message: String, - checkPermission: Boolean + checkPermission: Boolean, ): CommandExecuteResult = CommandManagerImpl.run { executeCommand(message, checkPermission) } override suspend fun Command.execute( sender: CommandSender, arguments: String, - checkPermission: Boolean + checkPermission: Boolean, ): CommandExecuteResult = CommandManagerImpl.run { execute(sender, arguments, checkPermission) } override suspend fun CommandSender.executeCommand( message: Message, - checkPermission: Boolean + checkPermission: Boolean, ): CommandExecuteResult = CommandManagerImpl.run { executeCommand(message, checkPermission) } + + /** + * 执行一个确切的指令 + * @see execute 获取更多信息 + */ + public suspend fun CommandSender.execute( + command: Command, + arguments: Message, + checkPermission: Boolean = true, + ): CommandExecuteResult { + return command.execute(this, arguments, checkPermission) + } + + /** + * 执行一个确切的指令 + * @see execute 获取更多信息 + */ + public suspend fun CommandSender.execute( + command: Command, + arguments: String, + checkPermission: Boolean = true, + ): CommandExecuteResult { + return command.execute(this, arguments, checkPermission) + } } } \ No newline at end of file From 6ebad54856aa5914d802f540ea309cc93b7e7ad0 Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 19:10:41 +0800 Subject: [PATCH 13/14] Fix compilation --- .../kotlin/net/mamoe/mirai/console/command/Command.kt | 8 ++++---- buildSrc/src/main/kotlin/Versions.kt | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt index 5a29b2559..1f70a38ba 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt @@ -84,13 +84,13 @@ public interface Command { @JvmStatic public val Command.primaryName: String get() = names[0] - - @JvmSynthetic - public suspend inline fun Command.onCommand(sender: CommandSender, args: MessageChain): Unit = - sender.run { onCommand(args) } } } +@JvmSynthetic +public suspend inline fun Command.onCommand(sender: CommandSender, args: MessageChain): Unit = + sender.onCommand(args) + /** * [Command] 的基础实现 * diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 069901671..98382a83e 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -18,7 +18,7 @@ object Versions { const val core = "1.2.3" - const val console = "1.0-M4-dev-5" + const val console = "1.0-M4-dev-7" const val consoleGraphical = "0.0.7" const val consoleTerminal = "0.1.0" const val consolePure = console From c5e68885c7893399b8abe5631f742a2e3376c50a Mon Sep 17 00:00:00 2001 From: Him188 Date: Sat, 12 Sep 2020 19:26:36 +0800 Subject: [PATCH 14/14] Public API stabilization: Review and remove ExperimentalPermission annotations --- .../console/MiraiConsoleImplementation.kt | 4 +- .../mirai/console/command/BuiltInCommands.kt | 9 ++-- .../mamoe/mirai/console/command/Command.kt | 9 ++-- .../mirai/console/command/CommandOwner.kt | 2 - .../mirai/console/command/CommandSender.kt | 12 +---- .../mirai/console/command/CompositeCommand.kt | 7 +-- .../mamoe/mirai/console/command/RawCommand.kt | 6 +-- .../mirai/console/command/SimpleCommand.kt | 5 +- .../description/CommandArgumentContext.kt | 4 +- .../CommandArgumentParserBuiltins.kt | 5 +- .../console/command/java/JCompositeCommand.kt | 6 +-- .../mirai/console/command/java/JRawCommand.kt | 4 +- .../console/command/java/JSimpleCommand.kt | 4 +- .../console/extension/ComponentStorage.kt | 2 - .../extensions/PermissionServiceProvider.kt | 4 -- .../MiraiConsoleImplementationBridge.kt | 2 - .../command/CompositeCommandInternal.kt | 17 +++--- .../command/executeCommandInternal.kt | 2 - .../console/internal/command/internal.kt | 52 ------------------- .../data/MultiFilePluginDataStorageImpl.kt | 2 - .../AbstractConcurrentPermissionService.kt | 4 -- .../permission/BuiltInPermissionServices.kt | 8 --- .../permission/parseFromStringImpl.kt | 2 - .../internal/plugin/JvmPluginInternal.kt | 8 --- .../console/permission/PermissionService.kt | 14 ++++- .../console/plugin/jvm/AbstractJvmPlugin.kt | 3 ++ .../mirai/console/plugin/jvm/JvmPlugin.kt | 2 - buildSrc/src/main/kotlin/Versions.kt | 11 +--- 28 files changed, 47 insertions(+), 163 deletions(-) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt index 42e03786f..d462676cc 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/MiraiConsoleImplementation.kt @@ -37,8 +37,8 @@ import kotlin.coroutines.CoroutineContext * * 这些 API 只应由前端实现者使用, 而不应该被插件或其他调用者使用. */ -@Retention(AnnotationRetention.SOURCE) -@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +@RequiresOptIn(level = RequiresOptIn.Level.ERROR) @Target(CLASS, TYPEALIAS, FUNCTION, PROPERTY, FIELD, CONSTRUCTOR) @MustBeDocumented public annotation class ConsoleFrontEndImplementation diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt index fe39c5268..c43db9d68 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/BuiltInCommands.kt @@ -19,11 +19,14 @@ import net.mamoe.mirai.console.command.description.* import net.mamoe.mirai.console.internal.command.CommandManagerImpl import net.mamoe.mirai.console.internal.command.CommandManagerImpl.allRegisteredCommands import net.mamoe.mirai.console.internal.util.runIgnoreException -import net.mamoe.mirai.console.permission.* +import net.mamoe.mirai.console.permission.Permission +import net.mamoe.mirai.console.permission.PermissionId +import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService.Companion.denyPermission import net.mamoe.mirai.console.permission.PermissionService.Companion.findCorrespondingPermissionOrFail import net.mamoe.mirai.console.permission.PermissionService.Companion.getPermittedPermissions import net.mamoe.mirai.console.permission.PermissionService.Companion.grantPermission +import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.console.util.ConsoleInternalApi import net.mamoe.mirai.event.events.EventCancelledException @@ -44,7 +47,6 @@ internal interface BuiltInCommandInternal : Command, BuiltInCommand * 内建指令列表 */ @Suppress("unused") -@OptIn(ExperimentalPermission::class) public object BuiltInCommands { @ConsoleExperimentalApi public val parentPermission: Permission by lazy { @@ -145,12 +147,11 @@ public object BuiltInCommands { } } - @OptIn(ExperimentalPermission::class) public object PermissionCommand : CompositeCommand( ConsoleCommandOwner, "permission", "权限", "perm", description = "Manage permissions", overrideContext = buildCommandArgumentContext { - PermitteeId::class with PermissibleIdentifierArgumentParser + PermitteeId::class with PermitteeIdArgumentParser Permission::class with PermissionIdArgumentParser.map { id -> kotlin.runCatching { id.findCorrespondingPermissionOrFail() diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt index 1f70a38ba..a746b50e8 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/Command.kt @@ -17,7 +17,6 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.register import net.mamoe.mirai.console.command.java.JCommand import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission import net.mamoe.mirai.console.internal.command.isValidSubName -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.SingleMessage @@ -42,12 +41,12 @@ public interface Command { public val names: Array /** - * 用法说明, 用于发送给用户. 一般 [usage] 包含 [description]. + * 用法说明, 用于发送给用户. [usage] 一般包含 [description]. */ public val usage: String /** - * 指令描述, 用于显示在 [BuiltInCommands.Help] + * 指令描述, 用于显示在 [BuiltInCommands.HelpCommand] */ public val description: String @@ -99,7 +98,6 @@ public suspend inline fun Command.onCommand(sender: CommandSender, args: Message * @see RawCommand */ public abstract class AbstractCommand -@OptIn(ExperimentalPermission::class) @JvmOverloads constructor( /** 指令拥有者. */ public override val owner: CommandOwner, @@ -107,7 +105,7 @@ public abstract class AbstractCommand description: String = "", parentPermission: Permission = owner.parentPermission, /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ - public override val prefixOptional: Boolean = false + public override val prefixOptional: Boolean = false, ) : Command { public override val description: String = description.trimIndent() public override val names: Array = @@ -115,6 +113,5 @@ public abstract class AbstractCommand list.firstOrNull { !it.isValidSubName() }?.let { error("Invalid name: $it") } }.toTypedArray() - @OptIn(ExperimentalPermission::class) public override val permission: Permission by lazy { createOrFindCommandPermission(parentPermission) } } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt index 22a988511..05685e137 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandOwner.kt @@ -10,7 +10,6 @@ package net.mamoe.mirai.console.command import net.mamoe.mirai.console.command.CommandManager.INSTANCE.unregisterAllCommands -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.permission.PermissionIdNamespace @@ -24,7 +23,6 @@ import net.mamoe.mirai.console.plugin.jvm.JvmPlugin * * @see JvmPlugin 是一个 [CommandOwner] */ -@OptIn(ExperimentalPermission::class) public interface CommandOwner : PermissionIdNamespace { /** * 在构造指令时, [Command.permission] 默认会使用 [parentPermission] 作为 [Permission.parent] diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt index 10a1bd6d9..89e05b099 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CommandSender.kt @@ -9,7 +9,7 @@ @file:Suppress( "NOTHING_TO_INLINE", "INAPPLICABLE_JVM_NAME", "FunctionName", "SuspendFunctionOnCoroutineScope", - "unused", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER" + "unused" ) package net.mamoe.mirai.console.command @@ -33,7 +33,6 @@ import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip import net.mamoe.mirai.console.internal.data.castOrNull import net.mamoe.mirai.console.internal.plugin.rootCauseOrSelf import net.mamoe.mirai.console.permission.AbstractPermitteeId -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permittee import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.console.util.ConsoleExperimentalApi @@ -47,7 +46,6 @@ import net.mamoe.mirai.message.data.PlainText import kotlin.contracts.InvocationKind import kotlin.contracts.contract import kotlin.coroutines.CoroutineContext -import kotlin.internal.LowPriorityInOverloadResolution /** * 指令发送者. @@ -136,7 +134,6 @@ import kotlin.internal.LowPriorityInOverloadResolution * @see toCommandSender * @see asCommandSender */ -@OptIn(ExperimentalPermission::class) public interface CommandSender : CoroutineScope, Permittee { /** * 与这个 [CommandSender] 相关的 [Bot]. @@ -441,7 +438,6 @@ public fun CommandSender.isNotUser(): Boolean { * @return [ifIsConsole] 或 [ifIsUser] 执行结果. */ @JvmSynthetic -@LowPriorityInOverloadResolution public inline fun CommandSender.fold( ifIsConsole: ConsoleCommandSender.() -> R, ifIsUser: UserCommandSender.() -> R, @@ -464,7 +460,7 @@ public inline fun CommandSender.fold( * * ### 实验性 API * - * 这是预览版本 API. 如果你对 [UserCommandSender.fold] 有建议, 请在 [mamoe/mirai-console/issues](https://github.com/mamoe/mirai-console/issues/new) 提交. + * 这是预览版本 API. 如果你对 [UserCommandSender.foldContext] 有建议, 请在 [mamoe/mirai-console/issues](https://github.com/mamoe/mirai-console/issues/new) 提交. * * @return [inGroup] 或 [inPrivate] 执行结果. */ @@ -517,7 +513,6 @@ public abstract class ConsoleCommandSender @ConsoleFrontEndImplementation constr public final override val name: String get() = NAME public final override fun toString(): String = NAME - @ExperimentalPermission public final override val permitteeId: AbstractPermitteeId.Console = AbstractPermitteeId.Console public companion object INSTANCE : ConsoleCommandSender(), CoroutineScope { @@ -615,7 +610,6 @@ public open class FriendCommandSender internal constructor( public override val subject: Contact get() = user public override fun toString(): String = "FriendCommandSender($user)" - @ExperimentalPermission public override val permitteeId: PermitteeId = AbstractPermitteeId.ExactFriend(user.id) @JvmBlockingBridge @@ -638,7 +632,6 @@ public open class MemberCommandSender internal constructor( public override val subject: Group get() = group public override fun toString(): String = "MemberCommandSender($user)" - @ExperimentalPermission public override val permitteeId: PermitteeId = AbstractPermitteeId.ExactMember(group.id, user.id) @JvmBlockingBridge @@ -661,7 +654,6 @@ public open class TempCommandSender internal constructor( public override val subject: Contact get() = group public override fun toString(): String = "TempCommandSender($user)" - @ExperimentalPermission public override val permitteeId: PermitteeId = AbstractPermitteeId.ExactTemp(user.group.id, user.id) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt index bf3fe97f5..5cd7bdb2b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/CompositeCommand.kt @@ -20,9 +20,7 @@ package net.mamoe.mirai.console.command import net.mamoe.mirai.console.command.description.* import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand import net.mamoe.mirai.console.internal.command.CompositeCommandSubCommandAnnotationResolver -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission -import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.message.data.MessageChain import kotlin.annotation.AnnotationRetention.RUNTIME import kotlin.annotation.AnnotationTarget.FUNCTION @@ -81,14 +79,13 @@ import kotlin.annotation.AnnotationTarget.FUNCTION * * @see buildCommandArgumentContext */ -@ConsoleExperimentalApi -public abstract class CompositeCommand @OptIn(ExperimentalPermission::class) constructor( +public abstract class CompositeCommand( owner: CommandOwner, vararg names: String, description: String = "no description available", parentPermission: Permission = owner.parentPermission, prefixOptional: Boolean = false, - overrideContext: CommandArgumentContext = EmptyCommandArgumentContext + overrideContext: CommandArgumentContext = EmptyCommandArgumentContext, ) : Command, AbstractReflectionCommand(owner, names, description, parentPermission, prefixOptional), CommandArgumentContextAware { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt index c52a32052..621172e97 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/RawCommand.kt @@ -15,7 +15,6 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.execute import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand import net.mamoe.mirai.console.command.java.JRawCommand import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.message.data.MessageChain @@ -30,7 +29,7 @@ import net.mamoe.mirai.message.data.MessageChain * @see SimpleCommand 简单指令 * @see CompositeCommand 复合指令 */ -public abstract class RawCommand @OptIn(ExperimentalPermission::class) constructor( +public abstract class RawCommand( /** * 指令拥有者. * @see CommandOwner @@ -45,9 +44,8 @@ public abstract class RawCommand @OptIn(ExperimentalPermission::class) construct /** 指令父权限 */ parentPermission: Permission = owner.parentPermission, /** 为 `true` 时表示 [指令前缀][CommandManager.commandPrefix] 可选 */ - public override val prefixOptional: Boolean = false + public override val prefixOptional: Boolean = false, ) : Command { - @OptIn(ExperimentalPermission::class) public override val permission: Permission by lazy { createOrFindCommandPermission(parentPermission) } /** diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt index abc94c388..55e5ef438 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/SimpleCommand.kt @@ -22,7 +22,6 @@ import net.mamoe.mirai.console.command.description.* import net.mamoe.mirai.console.command.java.JSimpleCommand import net.mamoe.mirai.console.internal.command.AbstractReflectionCommand import net.mamoe.mirai.console.internal.command.SimpleCommandSubCommandAnnotationResolver -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.message.data.MessageChain @@ -49,13 +48,13 @@ import net.mamoe.mirai.message.data.MessageChain * @see JSimpleCommand Java 实现 * @see [CommandManager.executeCommand] */ -public abstract class SimpleCommand @OptIn(ExperimentalPermission::class) constructor( +public abstract class SimpleCommand( owner: CommandOwner, vararg names: String, description: String = "no description available", parentPermission: Permission = owner.parentPermission, prefixOptional: Boolean = false, - overrideContext: CommandArgumentContext = EmptyCommandArgumentContext + overrideContext: CommandArgumentContext = EmptyCommandArgumentContext, ) : Command, AbstractReflectionCommand(owner, names, description, parentPermission, prefixOptional), CommandArgumentContextAware { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt index 714bc639a..8cf2456b5 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentContext.kt @@ -16,7 +16,6 @@ import net.mamoe.mirai.console.command.CommandSender import net.mamoe.mirai.console.command.CompositeCommand import net.mamoe.mirai.console.command.SimpleCommand import net.mamoe.mirai.console.command.description.CommandArgumentContext.ParserPair -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.console.util.ConsoleExperimentalApi @@ -66,7 +65,6 @@ public interface CommandArgumentContext { /** * 内建的默认 [CommandArgumentParser] */ - @OptIn(ExperimentalPermission::class) public object Builtins : CommandArgumentContext by (buildCommandArgumentContext { Int::class with IntArgumentParser Byte::class with ByteArgumentParser @@ -85,7 +83,7 @@ public interface CommandArgumentContext { Bot::class with ExistingBotArgumentParser PermissionId::class with PermissionIdArgumentParser - PermitteeId::class with PermissibleIdentifierArgumentParser + PermitteeId::class with PermitteeIdArgumentParser }) } diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt index 91cfffcae..9e5e22fe4 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/description/CommandArgumentParserBuiltins.kt @@ -14,7 +14,6 @@ import net.mamoe.mirai.console.command.* import net.mamoe.mirai.console.command.CommandSender.Companion.asCommandSender import net.mamoe.mirai.console.internal.command.fuzzySearchMember import net.mamoe.mirai.console.permission.AbstractPermitteeId -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.permission.PermitteeId import net.mamoe.mirai.contact.* @@ -308,7 +307,6 @@ public object ExistingMemberArgumentParser : InternalCommandArgumentParserExtens } } -@ExperimentalPermission public object PermissionIdArgumentParser : CommandArgumentParser { override fun parse(raw: String, sender: CommandSender): PermissionId { return kotlin.runCatching { PermissionId.parseFromString(raw) }.getOrElse { @@ -317,8 +315,7 @@ public object PermissionIdArgumentParser : CommandArgumentParser { } } -@ExperimentalPermission -public object PermissibleIdentifierArgumentParser : CommandArgumentParser { +public object PermitteeIdArgumentParser : CommandArgumentParser { override fun parse(raw: String, sender: CommandSender): PermitteeId { return if (raw == "~") sender.permitteeId else kotlin.runCatching { AbstractPermitteeId.parseFromString(raw) }.getOrElse { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt index 2c62b5959..6dacd29ac 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JCompositeCommand.kt @@ -14,9 +14,7 @@ import net.mamoe.mirai.console.command.CommandManager import net.mamoe.mirai.console.command.CommandOwner import net.mamoe.mirai.console.command.CompositeCommand import net.mamoe.mirai.console.command.description.buildCommandArgumentContext -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission -import net.mamoe.mirai.console.util.ConsoleExperimentalApi /** * 复合指令. 指令注册时候会通过反射构造指令解析器. @@ -68,8 +66,7 @@ import net.mamoe.mirai.console.util.ConsoleExperimentalApi * * @see buildCommandArgumentContext */ -@ConsoleExperimentalApi -public abstract class JCompositeCommand @OptIn(ExperimentalPermission::class) +public abstract class JCompositeCommand @JvmOverloads constructor( owner: CommandOwner, vararg names: String, @@ -79,7 +76,6 @@ public abstract class JCompositeCommand @OptIn(ExperimentalPermission::class) public final override var description: String = "" protected set - @OptIn(ExperimentalPermission::class) public final override var permission: Permission = super.permission protected set diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JRawCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JRawCommand.kt index 7767f204c..07b03c641 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JRawCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JRawCommand.kt @@ -14,7 +14,6 @@ import kotlinx.coroutines.withContext import net.mamoe.mirai.console.command.* import net.mamoe.mirai.console.command.CommandManager.INSTANCE.execute import net.mamoe.mirai.console.internal.command.createOrFindCommandPermission -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.SingleMessage @@ -45,7 +44,7 @@ import net.mamoe.mirai.message.data.SingleMessage * * @see JRawCommand */ -public abstract class JRawCommand @OptIn(ExperimentalPermission::class) +public abstract class JRawCommand @JvmOverloads constructor( /** * 指令拥有者. @@ -65,7 +64,6 @@ public abstract class JRawCommand @OptIn(ExperimentalPermission::class) protected set /** 指令权限 */ - @ExperimentalPermission public final override var permission: Permission = createOrFindCommandPermission(parentPermission) protected set diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JSimpleCommand.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JSimpleCommand.kt index 212c3850a..37f7022b9 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JSimpleCommand.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/command/java/JSimpleCommand.kt @@ -14,7 +14,6 @@ import net.mamoe.mirai.console.command.CommandManager.INSTANCE.executeCommand import net.mamoe.mirai.console.command.CommandOwner import net.mamoe.mirai.console.command.SimpleCommand import net.mamoe.mirai.console.command.description.CommandArgumentContext -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission /** @@ -40,7 +39,7 @@ import net.mamoe.mirai.console.permission.Permission * @see SimpleCommand * @see [CommandManager.executeCommand] */ -public abstract class JSimpleCommand @OptIn(ExperimentalPermission::class) constructor( +public abstract class JSimpleCommand( owner: CommandOwner, vararg names: String, basePermission: Permission, @@ -48,7 +47,6 @@ public abstract class JSimpleCommand @OptIn(ExperimentalPermission::class) const public override var description: String = super.description protected set - @ExperimentalPermission public override var permission: Permission = super.permission protected set public override var prefixOptional: Boolean = super.prefixOptional diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt index 6886e3da4..952e11e7e 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extension/ComponentStorage.kt @@ -7,7 +7,6 @@ import net.mamoe.mirai.console.extensions.PermissionServiceProvider import net.mamoe.mirai.console.extensions.SingletonExtensionSelector import net.mamoe.mirai.console.extensions.SingletonExtensionSelector.ExtensionPoint.selectSingleton import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.name @@ -67,7 +66,6 @@ public class ScopedComponentStorage( /** * 注册一个 [PermissionService] */ - @ExperimentalPermission public fun contributePermissionService( lazyInstance: () -> PermissionService<*>, ) { diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt index f0a8308c2..5db869bb8 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/extensions/PermissionServiceProvider.kt @@ -3,7 +3,6 @@ package net.mamoe.mirai.console.extensions import net.mamoe.mirai.console.extension.AbstractExtensionPoint import net.mamoe.mirai.console.extension.SingletonExtension import net.mamoe.mirai.console.extension.SingletonExtensionPoint -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionService /** @@ -11,17 +10,14 @@ import net.mamoe.mirai.console.permission.PermissionService * * 当插件注册 [PermissionService] 后, 默认会使用插件的 [PermissionService]. */ -@ExperimentalPermission public interface PermissionServiceProvider : SingletonExtension> { public companion object ExtensionPoint : AbstractExtensionPoint(PermissionServiceProvider::class), SingletonExtensionPoint } -@ExperimentalPermission public class PermissionServiceProviderImpl(override val instance: PermissionService<*>) : PermissionServiceProvider -@ExperimentalPermission public class LazyPermissionServiceProviderImpl(initializer: () -> PermissionService<*>) : PermissionServiceProvider { override val instance: PermissionService<*> by lazy(initializer) } \ No newline at end of file diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt index f9ebc4e55..1170d35cc 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/MiraiConsoleImplementationBridge.kt @@ -39,7 +39,6 @@ import net.mamoe.mirai.console.internal.extensions.BuiltInSingletonExtensionSele import net.mamoe.mirai.console.internal.permission.BuiltInPermissionService import net.mamoe.mirai.console.internal.plugin.PluginManagerImpl import net.mamoe.mirai.console.internal.util.autoHexToBytes -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.console.permission.PermissionService.Companion.grantPermission import net.mamoe.mirai.console.permission.RootPermission @@ -93,7 +92,6 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI override fun createLogger(identity: String?): MiraiLogger = instance.createLogger(identity) - @OptIn(ConsoleExperimentalApi::class, ExperimentalPermission::class) @Suppress("RemoveRedundantBackticks") internal fun doStart() { phase `greeting`@{ diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt index d7027b48b..0a3948277 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/CompositeCommandInternal.kt @@ -16,7 +16,6 @@ import net.mamoe.mirai.console.command.Command.Companion.primaryName import net.mamoe.mirai.console.command.description.CommandArgumentContext import net.mamoe.mirai.console.command.description.CommandArgumentContextAware import net.mamoe.mirai.console.internal.data.kClassQualifiedNameOrTip -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission import net.mamoe.mirai.message.data.* @@ -46,13 +45,13 @@ internal object SimpleCommandSubCommandAnnotationResolver : baseCommand.names } -internal abstract class AbstractReflectionCommand @OptIn(ExperimentalPermission::class) +internal abstract class AbstractReflectionCommand @JvmOverloads constructor( owner: CommandOwner, names: Array, description: String = "", parentPermission: Permission = owner.parentPermission, - prefixOptional: Boolean = false + prefixOptional: Boolean = false, ) : Command, AbstractCommand( owner, names = names, @@ -120,27 +119,26 @@ internal abstract class AbstractReflectionCommand @OptIn(ExperimentalPermission: } } - internal class DefaultSubCommandDescriptor @OptIn(ExperimentalPermission::class) constructor( + internal class DefaultSubCommandDescriptor( val description: String, val permission: Permission, - val onCommand: suspend (sender: CommandSender, rawArgs: MessageChain) -> Unit + val onCommand: suspend (sender: CommandSender, rawArgs: MessageChain) -> Unit, ) - internal inner class SubCommandDescriptor @OptIn(ExperimentalPermission::class) constructor( + internal inner class SubCommandDescriptor( val names: Array, val params: Array>, val description: String, val permission: Permission, val onCommand: suspend (sender: CommandSender, parsedArgs: Array) -> Boolean, - val context: CommandArgumentContext + val context: CommandArgumentContext, ) { val usage: String = createUsage(this@AbstractReflectionCommand) - @OptIn(ExperimentalPermission::class) internal suspend fun parseAndExecute( sender: CommandSender, argsWithSubCommandNameNotRemoved: MessageChain, - removeSubName: Boolean + removeSubName: Boolean, ) { val args = parseArgs(sender, argsWithSubCommandNameNotRemoved, if (removeSubName) 1 else 0) if (!this.permission.testPermission(sender)) { @@ -251,7 +249,6 @@ internal fun AbstractReflectionCommand.SubCommandDescriptor.createUsage(baseComm appendLine() }.trimEnd() -@OptIn(ExperimentalPermission::class) internal fun AbstractReflectionCommand.createSubCommand( function: KFunction<*>, context: CommandArgumentContext diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt index 57414b6b5..703a7e062 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/executeCommandInternal.kt @@ -10,12 +10,10 @@ package net.mamoe.mirai.console.internal.command import net.mamoe.mirai.console.command.* -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionService.Companion.testPermission import net.mamoe.mirai.message.data.MessageChain import net.mamoe.mirai.message.data.asMessageChain -@OptIn(ExperimentalPermission::class) @JvmSynthetic @Throws(CommandExecutionException::class) internal suspend fun CommandSender.executeCommandInternal( diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt index 876ca8f95..3bf578354 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/command/internal.kt @@ -11,7 +11,6 @@ package net.mamoe.mirai.console.internal.command import net.mamoe.mirai.console.command.Command import net.mamoe.mirai.console.command.Command.Companion.primaryName -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.Permission import net.mamoe.mirai.console.permission.PermissionService import net.mamoe.mirai.contact.Group @@ -53,56 +52,6 @@ internal fun String.fuzzyMatchWith(target: String): Double { return match.toDouble() / (longerLength + (shorterLength - match)) } -internal inline fun Collection.fuzzySearch( - target: String, - crossinline index: (T) -> String -): T? { - var maxElement: T? = null - var max = 0.0 - - for (t in this) { - val r = index(t).fuzzyMatchWith(target) - if (r > max) { - maxElement = t - max = r - } - } - - if (max >= 0.7) { - return maxElement - } - return null -} - -/** - * 模糊搜索一个List中index最接近target的东西 - * 并且确保target是唯一的 - * 如搜索index为XXXXYY list中同时存在XXXXYYY XXXXYYYY 将返回null - */ -internal inline fun Collection.fuzzySearchOnly( - target: String, - index: (T) -> String -): T? { - var potential: T? = null - var rate = 0.0 - var collide = 0 - this.forEach { - with(index(it).fuzzyMatchWith(target)) { - if (this > rate) { - rate = this - potential = it - } - if (this == 1.0) { - collide++ - } - if (collide > 1) { - return null//collide - } - } - } - return potential -} - /** * @return candidates @@ -138,7 +87,6 @@ internal fun Group.fuzzySearchMember( } } -@OptIn(ExperimentalPermission::class) internal fun Command.createOrFindCommandPermission(parent: Permission): Permission { val id = owner.permissionId(primaryName) return PermissionService.INSTANCE[id] ?: PermissionService.INSTANCE.register(id, description, parent) diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt index 8b8abc116..a753a52cd 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/data/MultiFilePluginDataStorageImpl.kt @@ -14,7 +14,6 @@ import net.mamoe.mirai.console.data.PluginData import net.mamoe.mirai.console.data.PluginDataHolder import net.mamoe.mirai.console.data.PluginDataStorage import net.mamoe.mirai.console.internal.command.qualifiedNameOrTip -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.utils.MiraiLogger import net.mamoe.mirai.utils.SilentLogger @@ -65,7 +64,6 @@ internal open class MultiFilePluginDataStorageImpl( @ConsoleExperimentalApi public override fun store(holder: PluginDataHolder, instance: PluginData) { - @OptIn(ExperimentalPermission::class) val yaml =/* if (instance.saveName == "PermissionService") Json { prettyPrint = true ignoreUnknownKeys = true diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/AbstractConcurrentPermissionService.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/AbstractConcurrentPermissionService.kt index 7bdc4bedf..31641db0b 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/AbstractConcurrentPermissionService.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/AbstractConcurrentPermissionService.kt @@ -13,10 +13,6 @@ import net.mamoe.mirai.console.data.PluginDataExtensions import net.mamoe.mirai.console.permission.* import net.mamoe.mirai.console.permission.PermitteeId.Companion.hasChild -/** - * - */ -@ExperimentalPermission internal abstract class AbstractConcurrentPermissionService

: PermissionService

{ protected abstract val permissions: MutableMap protected abstract val grantedPermissionsMap: PluginDataExtensions.NotNullMutableMap> diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/BuiltInPermissionServices.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/BuiltInPermissionServices.kt index a49fcfdb2..2d2271312 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/BuiltInPermissionServices.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/internal/permission/BuiltInPermissionServices.kt @@ -21,7 +21,6 @@ import kotlin.reflect.KClass import kotlin.reflect.full.isSuperclassOf @Suppress("unused") // don't pollute top-level -@OptIn(ExperimentalPermission::class) internal fun PermissionService<*>.checkType(permissionType: KClass): PermissionService { require(this.permissionType.isSuperclassOf(permissionType)) { "Custom-constructed Permission instance is not allowed (Required ${this.permissionType}, found ${permissionType}. " + @@ -32,7 +31,6 @@ internal fun PermissionService<*>.checkType(permissionType: KClass } -@ExperimentalPermission internal object AllPermitPermissionService : PermissionService { private val all = ConcurrentHashMap() override val permissionType: KClass get() = PermissionImpl::class @@ -65,10 +63,8 @@ internal object AllPermitPermissionService : PermissionService { } @Suppress("DEPRECATION") -@OptIn(ExperimentalPermission::class) private val RootPermissionImpl = PermissionImpl(PermissionId("*", "*"), "The root permission").also { it.parent = it } -@ExperimentalPermission internal object AllDenyPermissionService : PermissionService { private val all = ConcurrentHashMap() override val permissionType: KClass @@ -101,11 +97,9 @@ internal object AllDenyPermissionService : PermissionService { } } -@ExperimentalPermission internal object BuiltInPermissionService : AbstractConcurrentPermissionService(), PermissionService { - @ExperimentalPermission override val permissionType: KClass get() = PermissionImpl::class override val permissions: ConcurrentHashMap = ConcurrentHashMap() @@ -122,7 +116,6 @@ internal object BuiltInPermissionService : AbstractConcurrentPermissionService

{ - @ExperimentalPermission + /** + * [P] 的类型 + */ public val permissionType: KClass

+ + /** + * [RootPermission] 的实现 + */ public val rootPermission: P /////////////////////////////////////////////////////////////////////////// + /** + * 获取一个已经 [注册][register] 了的 [P] + */ public operator fun get(id: PermissionId): P? + /** + * 获取所有已注册的指令列表. 应保证线程安全. + */ public fun getRegisteredPermissions(): Sequence

/** diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt index 23e63ab7a..347f3be21 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/AbstractJvmPlugin.kt @@ -15,6 +15,7 @@ import net.mamoe.mirai.console.data.AutoSavePluginDataHolder import net.mamoe.mirai.console.data.PluginConfig import net.mamoe.mirai.console.data.PluginData import net.mamoe.mirai.console.internal.plugin.JvmPluginInternal +import net.mamoe.mirai.console.permission.PermissionId import net.mamoe.mirai.console.util.ConsoleExperimentalApi import net.mamoe.mirai.utils.minutesToMillis import net.mamoe.mirai.utils.secondsToMillis @@ -36,6 +37,8 @@ public abstract class AbstractJvmPlugin @JvmOverloads constructor( public final override val loader: JarPluginLoader get() = super.loader + public final override fun permissionId(id: String): PermissionId = PermissionId(description.id, id) + /** * 重载 [PluginData] * diff --git a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt index bfb986340..ae303154a 100644 --- a/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt +++ b/backend/mirai-console/src/main/kotlin/net/mamoe/mirai/console/plugin/jvm/JvmPlugin.kt @@ -19,7 +19,6 @@ package net.mamoe.mirai.console.plugin.jvm import kotlinx.coroutines.CoroutineScope import net.mamoe.mirai.console.extension.ScopedComponentStorage -import net.mamoe.mirai.console.permission.ExperimentalPermission import net.mamoe.mirai.console.permission.PermissionIdNamespace import net.mamoe.mirai.console.plugin.Plugin import net.mamoe.mirai.console.plugin.PluginFileExtensions @@ -38,7 +37,6 @@ import net.mamoe.mirai.utils.MiraiLogger * @see JvmPlugin 支持文件系统扩展 * @see ResourceContainer 支持资源获取 (如 Jar 中的资源文件) */ -@OptIn(ExperimentalPermission::class) public interface JvmPlugin : Plugin, CoroutineScope, PluginFileExtensions, ResourceContainer, PermissionIdNamespace { diff --git a/buildSrc/src/main/kotlin/Versions.kt b/buildSrc/src/main/kotlin/Versions.kt index 98382a83e..35c61dad8 100644 --- a/buildSrc/src/main/kotlin/Versions.kt +++ b/buildSrc/src/main/kotlin/Versions.kt @@ -7,18 +7,9 @@ * https://github.com/mamoe/mirai/blob/master/LICENSE */ -/* - * Copyright 2019-2020 Mamoe Technologies and contributors. - * - * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. - * Use of this source code is governed by the GNU AFFERO GENERAL PUBLIC LICENSE version 3 license that can be found via the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - object Versions { const val core = "1.2.3" - const val console = "1.0-M4-dev-7" + const val console = "1.0-M4-dev-8" const val consoleGraphical = "0.0.7" const val consoleTerminal = "0.1.0" const val consolePure = console