mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-11 02:50:15 +08:00
Introduce JvmPluginDescriptionBuilder, add checks
This commit is contained in:
parent
a70e00464f
commit
c76a6dacc9
@ -42,7 +42,6 @@ import net.mamoe.mirai.console.permission.RootPermission
|
|||||||
import net.mamoe.mirai.console.plugin.PluginLoader
|
import net.mamoe.mirai.console.plugin.PluginLoader
|
||||||
import net.mamoe.mirai.console.plugin.PluginManager
|
import net.mamoe.mirai.console.plugin.PluginManager
|
||||||
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
import net.mamoe.mirai.console.plugin.center.PluginCenter
|
||||||
import net.mamoe.mirai.console.util.BotManager
|
|
||||||
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.ConsoleInput
|
||||||
import net.mamoe.mirai.utils.*
|
import net.mamoe.mirai.utils.*
|
||||||
@ -121,8 +120,6 @@ internal object MiraiConsoleImplementationBridge : CoroutineScope, MiraiConsoleI
|
|||||||
phase `load configurations`@{
|
phase `load configurations`@{
|
||||||
mainLogger.verbose { "Loading configurations..." }
|
mainLogger.verbose { "Loading configurations..." }
|
||||||
ConsoleDataScope.reloadAll()
|
ConsoleDataScope.reloadAll()
|
||||||
|
|
||||||
BotManager
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val pluginLoadSession: PluginManagerImpl.PluginLoadSession
|
val pluginLoadSession: PluginManagerImpl.PluginLoadSession
|
||||||
|
@ -1,53 +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("MemberVisibilityCanBePrivate")
|
|
||||||
|
|
||||||
package net.mamoe.mirai.console.internal.data.builtins
|
|
||||||
|
|
||||||
import net.mamoe.mirai.Bot
|
|
||||||
import net.mamoe.mirai.console.data.AutoSavePluginConfig
|
|
||||||
import net.mamoe.mirai.console.data.PluginDataExtensions.mapKeys
|
|
||||||
import net.mamoe.mirai.console.data.PluginDataExtensions.withEmptyDefault
|
|
||||||
import net.mamoe.mirai.console.data.ValueDescription
|
|
||||||
import net.mamoe.mirai.console.data.value
|
|
||||||
import net.mamoe.mirai.console.util.BotManager
|
|
||||||
import net.mamoe.mirai.contact.User
|
|
||||||
|
|
||||||
internal object BotManagerImpl : BotManager {
|
|
||||||
override val User.isManager: Boolean get() = this.id in ManagersConfig[this.bot]
|
|
||||||
|
|
||||||
override fun Bot.removeManager(id: Long): Boolean {
|
|
||||||
return ManagersConfig[this].remove(id)
|
|
||||||
}
|
|
||||||
|
|
||||||
override val Bot.managers: List<Long>
|
|
||||||
get() = ManagersConfig[this].toList()
|
|
||||||
|
|
||||||
override fun Bot.addManager(id: Long): Boolean {
|
|
||||||
return ManagersConfig[this].add(id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal object ManagersConfig : AutoSavePluginConfig() {
|
|
||||||
override val saveName: String
|
|
||||||
get() = "Managers"
|
|
||||||
|
|
||||||
@ValueDescription(
|
|
||||||
"""
|
|
||||||
管理员列表
|
|
||||||
"""
|
|
||||||
)
|
|
||||||
private val managers
|
|
||||||
by value<MutableMap<Long, MutableSet<Long>>>()
|
|
||||||
.withEmptyDefault()
|
|
||||||
.mapKeys(Bot::getInstance, Bot::id)
|
|
||||||
|
|
||||||
internal operator fun get(bot: Bot): MutableSet<Long> = managers[bot]
|
|
||||||
}
|
|
@ -22,7 +22,7 @@ import net.mamoe.mirai.utils.minutesToMillis
|
|||||||
|
|
||||||
internal object ConsoleDataScope : CoroutineScope by MiraiConsole.childScope("ConsoleDataScope") {
|
internal object ConsoleDataScope : CoroutineScope by MiraiConsole.childScope("ConsoleDataScope") {
|
||||||
private val data: List<PluginData> = mutableListOf()
|
private val data: List<PluginData> = mutableListOf()
|
||||||
private val configs: MutableList<PluginConfig> = mutableListOf(ManagersConfig, AutoLoginConfig)
|
private val configs: MutableList<PluginConfig> = mutableListOf(AutoLoginConfig)
|
||||||
|
|
||||||
fun addAndReloadConfig(config: PluginConfig) {
|
fun addAndReloadConfig(config: PluginConfig) {
|
||||||
configs.add(config)
|
configs.add(config)
|
||||||
|
@ -171,8 +171,10 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
|
|||||||
|
|
||||||
@kotlin.jvm.Throws(PluginLoadException::class)
|
@kotlin.jvm.Throws(PluginLoadException::class)
|
||||||
internal fun checkPluginDescription(description: PluginDescription) {
|
internal fun checkPluginDescription(description: PluginDescription) {
|
||||||
when (description.name.toLowerCase()) {
|
kotlin.runCatching {
|
||||||
"main", "console", "plugin", "config", "data" -> throw PluginLoadException("Plugin name '${description.name}' is forbidden.")
|
PluginDescription.checkPluginDescription(description)
|
||||||
|
}.getOrElse {
|
||||||
|
throw PluginLoadException("PluginDescription check failed.", it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +216,7 @@ internal object PluginManagerImpl : PluginManager, CoroutineScope by MiraiConsol
|
|||||||
return cannotBeLoad
|
return cannotBeLoad
|
||||||
}
|
}
|
||||||
|
|
||||||
fun List<PluginDependency>.filterIsMissing(): List<PluginDependency> =
|
fun Collection<PluginDependency>.filterIsMissing(): List<PluginDependency> =
|
||||||
this.filterNot { it.isOptional || it in resolved }
|
this.filterNot { it.isOptional || it in resolved }
|
||||||
|
|
||||||
tailrec fun List<D>.doSort() {
|
tailrec fun List<D>.doSort() {
|
||||||
@ -257,4 +259,4 @@ internal fun PluginDescription.wrapWith(loader: PluginLoader<*, *>, plugin: Plug
|
|||||||
)
|
)
|
||||||
|
|
||||||
internal operator fun List<PluginDescription>.contains(dependency: PluginDependency): Boolean =
|
internal operator fun List<PluginDescription>.contains(dependency: PluginDependency): Boolean =
|
||||||
any { it.name == dependency.name }
|
any { it.id == dependency.id }
|
||||||
|
@ -82,4 +82,4 @@ public inline val Plugin.author: String get() = this.description.author
|
|||||||
/**
|
/**
|
||||||
* 获取 [PluginDescription.dependencies]
|
* 获取 [PluginDescription.dependencies]
|
||||||
*/
|
*/
|
||||||
public inline val Plugin.dependencies: List<PluginDependency> get() = this.description.dependencies
|
public inline val Plugin.dependencies: Set<PluginDependency> get() = this.description.dependencies
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
package net.mamoe.mirai.console.plugin.description
|
||||||
|
|
||||||
|
public class IllegalPluginDescriptionException : RuntimeException {
|
||||||
|
public constructor() : super()
|
||||||
|
public constructor(message: String?) : super(message)
|
||||||
|
public constructor(message: String?, cause: Throwable?) : super(message, cause)
|
||||||
|
public constructor(cause: Throwable?) : super(cause)
|
||||||
|
}
|
@ -18,9 +18,11 @@ import com.vdurmont.semver4j.Semver
|
|||||||
*
|
*
|
||||||
* @see PluginDescription.dependencies
|
* @see PluginDescription.dependencies
|
||||||
*/
|
*/
|
||||||
public data class PluginDependency(
|
public data class PluginDependency @JvmOverloads constructor(
|
||||||
/** 依赖插件名 */
|
/**
|
||||||
public val name: String,
|
* 依赖插件 ID, [PluginDescription.id]
|
||||||
|
*/
|
||||||
|
public val id: String,
|
||||||
/**
|
/**
|
||||||
* 依赖版本号. 为 null 时则为不限制版本.
|
* 依赖版本号. 为 null 时则为不限制版本.
|
||||||
*
|
*
|
||||||
@ -34,6 +36,16 @@ public data class PluginDependency(
|
|||||||
*/
|
*/
|
||||||
public val isOptional: Boolean = false
|
public val isOptional: Boolean = false
|
||||||
) {
|
) {
|
||||||
|
/**
|
||||||
|
* @see PluginDependency
|
||||||
|
*/
|
||||||
|
public constructor(name: String, isOptional: Boolean = false) : this(
|
||||||
|
name, null, isOptional
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see PluginDependency
|
||||||
|
*/
|
||||||
public constructor(name: String, version: String, isOptional: Boolean) : this(
|
public constructor(name: String, version: String, isOptional: Boolean) : this(
|
||||||
name,
|
name,
|
||||||
Semver(version, Semver.SemverType.IVY),
|
Semver(version, Semver.SemverType.IVY),
|
||||||
|
@ -11,6 +11,7 @@ package net.mamoe.mirai.console.plugin.description
|
|||||||
|
|
||||||
import com.vdurmont.semver4j.Semver
|
import com.vdurmont.semver4j.Semver
|
||||||
import net.mamoe.mirai.console.plugin.Plugin
|
import net.mamoe.mirai.console.plugin.Plugin
|
||||||
|
import net.mamoe.mirai.console.plugin.PluginLoadException
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -27,14 +28,44 @@ public interface PluginDescription {
|
|||||||
public val kind: PluginKind
|
public val kind: PluginKind
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 插件名称. 不允许存在 ":", 推荐全英文.
|
* 插件 ID, 必须全英文, 仅允许英文字母, '-', '_', '.'.
|
||||||
*
|
*
|
||||||
* 插件名称不能完全是以下其中一种.
|
* - 类似于 Java 包名, 插件 ID 需要 '域名.名称' 格式, 如 `net.mamoe.mirai.example-plugin`
|
||||||
|
* - 域名和名称都是必须的
|
||||||
|
* - '.' 不允许位于首位或末尾
|
||||||
|
* - '-' 和 '_' 仅允许存在于两个英文字母之间
|
||||||
|
*
|
||||||
|
* ID 在插件发布后就应该保持不变, 以便其他插件添加依赖.
|
||||||
|
*
|
||||||
|
* 插件 ID 的域名和名称都不能完全是以下其中一个 ([FORBIDDEN_ID_WORDS]).
|
||||||
|
* - "console"
|
||||||
|
* - "main"
|
||||||
|
* - "plugin"
|
||||||
|
* - "config"
|
||||||
|
* - "data"
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* ID 用于指令权限等一些内部处理
|
||||||
|
*
|
||||||
|
* @see FORBIDDEN_ID_LETTERS
|
||||||
|
* @see FORBIDDEN_ID_WORDS
|
||||||
|
*/
|
||||||
|
public val id: String
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 插件名称. 允许中文, 允许各类符号.
|
||||||
|
*
|
||||||
|
* 插件名称不能完全是以下其中一种 ([FORBIDDEN_ID_WORDS]).
|
||||||
* - console
|
* - console
|
||||||
* - main
|
* - main
|
||||||
* - plugin
|
* - plugin
|
||||||
* - config
|
* - config
|
||||||
* - data
|
* - data
|
||||||
|
*
|
||||||
|
* 插件名称用于显示给用户.
|
||||||
|
*
|
||||||
|
* @see FORBIDDEN_ID_LETTERS
|
||||||
|
* @see FORBIDDEN_ID_WORDS
|
||||||
*/
|
*/
|
||||||
public val name: String
|
public val name: String
|
||||||
|
|
||||||
@ -46,7 +77,21 @@ public interface PluginDescription {
|
|||||||
/**
|
/**
|
||||||
* 插件版本.
|
* 插件版本.
|
||||||
*
|
*
|
||||||
* 语法参考: ([语义化版本 2.0.0](https://semver.org/lang/zh-CN/))
|
* 语法参考: ([语义化版本 2.0.0](https://semver.org/lang/zh-CN/)).
|
||||||
|
*
|
||||||
|
* 合法的版本号示例:
|
||||||
|
* - `1.0.0`
|
||||||
|
* - `1.0`
|
||||||
|
* - `1.0-M1`
|
||||||
|
* - `1.0.0-M1`
|
||||||
|
* - `1.0.0-M2-1`
|
||||||
|
* - `1` (尽管非常不建议这么做)
|
||||||
|
*
|
||||||
|
* 非法版本号实例:
|
||||||
|
* - `DEBUG-1`
|
||||||
|
* - `-1.0`
|
||||||
|
* - `v1.0` (不允许 "v")
|
||||||
|
* - `V1.0` (不允许 "V")
|
||||||
*
|
*
|
||||||
* @see Semver 语义化版本. 允许 [宽松][Semver.SemverType.LOOSE] 类型版本.
|
* @see Semver 语义化版本. 允许 [宽松][Semver.SemverType.LOOSE] 类型版本.
|
||||||
*/
|
*/
|
||||||
@ -62,6 +107,77 @@ public interface PluginDescription {
|
|||||||
*
|
*
|
||||||
* @see PluginDependency
|
* @see PluginDependency
|
||||||
*/
|
*/
|
||||||
public val dependencies: List<PluginDependency>
|
public val dependencies: Set<PluginDependency>
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
public val FORBIDDEN_ID_LETTERS: Array<String> = "~!@#$%^&*()+/*<>{}|[]\\?".map(Char::toString).toTypedArray()
|
||||||
|
public val FORBIDDEN_ID_WORDS: Array<String> = arrayOf("main", "console", "plugin", "config", "data")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 依次检查 [PluginDescription] 的 [PluginDescription.id], [PluginDescription.name], [PluginDescription.dependencies] 的合法性
|
||||||
|
*
|
||||||
|
* @throws IllegalPluginDescriptionException 当不合法时抛出.
|
||||||
|
*/
|
||||||
|
@Throws(IllegalPluginDescriptionException::class)
|
||||||
|
public fun checkPluginDescription(instance: PluginDescription) {
|
||||||
|
kotlin.runCatching {
|
||||||
|
checkPluginId(instance.id)
|
||||||
|
checkPluginName(instance.name)
|
||||||
|
checkDependencies(instance.id, instance.dependencies)
|
||||||
|
}.getOrElse {
|
||||||
|
throw IllegalPluginDescriptionException(
|
||||||
|
"Illegal description. Plugin ${instance.name} (${instance.id})",
|
||||||
|
it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查 [PluginDescription.id] 的合法性.
|
||||||
|
*
|
||||||
|
* @throws IllegalPluginDescriptionException 当不合法时抛出.
|
||||||
|
*/
|
||||||
|
@Throws(IllegalPluginDescriptionException::class)
|
||||||
|
public fun checkPluginId(id: String) {
|
||||||
|
if (id.isBlank()) throw IllegalPluginDescriptionException("Plugin id cannot be blank")
|
||||||
|
if (id.count { it == '.' } < 2) throw IllegalPluginDescriptionException("'$id' is illegal. Plugin id must consist of both domain and name. ")
|
||||||
|
|
||||||
|
FORBIDDEN_ID_LETTERS.firstOrNull { it in id }?.let { illegal ->
|
||||||
|
throw IllegalPluginDescriptionException("Plugin id contains illegal char: $illegal.")
|
||||||
|
}
|
||||||
|
|
||||||
|
val idSections = id.split('.')
|
||||||
|
FORBIDDEN_ID_WORDS.firstOrNull { it in idSections }?.let { illegal ->
|
||||||
|
throw IllegalPluginDescriptionException("Plugin id contains illegal word: '$illegal'.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查 [PluginDescription.name] 的合法性.
|
||||||
|
*
|
||||||
|
* @throws IllegalPluginDescriptionException 当不合法时抛出.
|
||||||
|
*/
|
||||||
|
@Throws(IllegalPluginDescriptionException::class)
|
||||||
|
public fun checkPluginName(name: String) {
|
||||||
|
if (name.isBlank()) throw IllegalPluginDescriptionException("Plugin name cannot be blank")
|
||||||
|
FORBIDDEN_ID_WORDS.firstOrNull { it in name }?.let { illegal ->
|
||||||
|
throw IllegalPluginDescriptionException("Plugin name is illegal: '$illegal'.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查 [PluginDescription.dependencies] 的合法性.
|
||||||
|
*
|
||||||
|
* @throws IllegalPluginDescriptionException 当不合法时抛出.
|
||||||
|
*/
|
||||||
|
@Throws(IllegalPluginDescriptionException::class)
|
||||||
|
public fun checkDependencies(pluginId: String, dependencies: Set<PluginDependency>) {
|
||||||
|
if (dependencies.distinctBy { it.id }.size != dependencies.size)
|
||||||
|
throw PluginLoadException("Duplicated dependency detected: A plugin cannot depend on different versions of dependencies of the same id")
|
||||||
|
|
||||||
|
if (dependencies.any { it.id == pluginId })
|
||||||
|
throw PluginLoadException("Recursive dependency detected: A plugin cannot depend on itself")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("unused")
|
@file:Suppress("unused", "INVISIBLE_REFERENCE", "INVISIBLE_member")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.plugin.jvm
|
package net.mamoe.mirai.console.plugin.jvm
|
||||||
|
|
||||||
@ -15,35 +15,207 @@ import com.vdurmont.semver4j.Semver
|
|||||||
import net.mamoe.mirai.console.plugin.description.PluginDependency
|
import net.mamoe.mirai.console.plugin.description.PluginDependency
|
||||||
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
import net.mamoe.mirai.console.plugin.description.PluginDescription
|
||||||
import net.mamoe.mirai.console.plugin.description.PluginKind
|
import net.mamoe.mirai.console.plugin.description.PluginKind
|
||||||
|
import kotlin.internal.LowPriorityInOverloadResolution
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* JVM 插件的描述. 通常作为 `plugin.yml`
|
* JVM 插件的描述. 通常作为 `plugin.yml`
|
||||||
|
*
|
||||||
|
* 请不要自行实现 [JvmPluginDescription] 接口. 它不具有继承稳定性.
|
||||||
|
*
|
||||||
* @see SimpleJvmPluginDescription
|
* @see SimpleJvmPluginDescription
|
||||||
|
* @see JvmPluginDescriptionBuilder
|
||||||
*/
|
*/
|
||||||
public interface JvmPluginDescription : PluginDescription
|
public interface JvmPluginDescription : PluginDescription {
|
||||||
|
public companion object {
|
||||||
|
/**
|
||||||
|
* 构建 [JvmPluginDescription]
|
||||||
|
* @see JvmPluginDescriptionBuilder
|
||||||
|
*/
|
||||||
|
@JvmSynthetic
|
||||||
|
public operator fun invoke(
|
||||||
|
name: String,
|
||||||
|
version: String,
|
||||||
|
block: JvmPluginDescriptionBuilder.() -> Unit = {}
|
||||||
|
): JvmPluginDescription = JvmPluginDescriptionBuilder(name, version).apply(block).build()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 构建 [JvmPluginDescription]
|
||||||
|
* @see JvmPluginDescriptionBuilder
|
||||||
|
*/
|
||||||
|
@JvmSynthetic
|
||||||
|
public operator fun invoke(
|
||||||
|
name: String,
|
||||||
|
version: Semver,
|
||||||
|
block: JvmPluginDescriptionBuilder.() -> Unit = {}
|
||||||
|
): JvmPluginDescription = JvmPluginDescriptionBuilder(name, version).apply(block).build()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* [JvmPluginDescription] 构建器.
|
||||||
|
*
|
||||||
|
* #### Kotlin Example
|
||||||
|
* ```
|
||||||
|
* val desc = JvmPluginDescription("org.example.example-plugin", "1.0.0") {
|
||||||
|
* info("This is an example plugin")
|
||||||
|
* dependsOn("org.example.another-plugin")
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* #### Java Example
|
||||||
|
* ```
|
||||||
|
* JvmPluginDescription desc = new JvmPluginDescriptionBuilder("org.example.example-plugin", "1.0.0")
|
||||||
|
* .info("This is an example plugin")
|
||||||
|
* .dependsOn("org.example.another-plugin")
|
||||||
|
* .build()
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* @see [JvmPluginDescription.invoke]
|
||||||
|
*/
|
||||||
|
public class JvmPluginDescriptionBuilder(
|
||||||
|
private var id: String,
|
||||||
|
private var version: Semver,
|
||||||
|
) {
|
||||||
|
public constructor(name: String, version: String) : this(name, Semver(version, Semver.SemverType.LOOSE))
|
||||||
|
|
||||||
|
private var name: String = id
|
||||||
|
private var author: String = ""
|
||||||
|
private var info: String = ""
|
||||||
|
private var dependencies: MutableSet<PluginDependency> = mutableSetOf()
|
||||||
|
private var kind: PluginKind = PluginKind.NORMAL
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun name(value: String): JvmPluginDescriptionBuilder = apply { this.name = value.trim() }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun version(value: String): JvmPluginDescriptionBuilder =
|
||||||
|
apply { this.version = Semver(value, Semver.SemverType.LOOSE) }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun version(value: Semver): JvmPluginDescriptionBuilder = apply { this.version = value }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun id(value: String): JvmPluginDescriptionBuilder = apply { this.id = value.trim() }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun author(value: String): JvmPluginDescriptionBuilder = apply { this.author = value.trim() }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun info(value: String): JvmPluginDescriptionBuilder = apply { this.info = value.trimIndent() }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun kind(value: PluginKind): JvmPluginDescriptionBuilder = apply { this.kind = value }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun normalPlugin(): JvmPluginDescriptionBuilder = apply { this.kind = PluginKind.NORMAL }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun loaderProviderPlugin(): JvmPluginDescriptionBuilder = apply { this.kind = PluginKind.LOADER }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun highPriorityExtensionsPlugin(): JvmPluginDescriptionBuilder =
|
||||||
|
apply { this.kind = PluginKind.HIGH_PRIORITY_EXTENSIONS }
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun dependsOn(
|
||||||
|
pluginId: String,
|
||||||
|
version: String? = null,
|
||||||
|
isOptional: Boolean = false
|
||||||
|
): JvmPluginDescriptionBuilder = apply {
|
||||||
|
if (version == null) this.dependencies.add(PluginDependency(pluginId, version, isOptional))
|
||||||
|
else this.dependencies.add(PluginDependency(pluginId, version, isOptional))
|
||||||
|
}
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun setDependencies(
|
||||||
|
value: Set<PluginDependency>
|
||||||
|
): JvmPluginDescriptionBuilder = apply {
|
||||||
|
this.dependencies = value.toMutableSet()
|
||||||
|
}
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun dependsOn(
|
||||||
|
vararg dependencies: PluginDependency
|
||||||
|
): JvmPluginDescriptionBuilder = apply {
|
||||||
|
for (dependency in dependencies) {
|
||||||
|
this.dependencies.add(dependency)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ILoveKuriyamaMiraiForever
|
||||||
|
public fun dependsOn(
|
||||||
|
pluginId: String,
|
||||||
|
version: Semver? = null,
|
||||||
|
isOptional: Boolean = false
|
||||||
|
): JvmPluginDescriptionBuilder = apply { this.dependencies.add(PluginDependency(pluginId, version, isOptional)) }
|
||||||
|
|
||||||
|
|
||||||
|
@Suppress("DEPRECATION_ERROR")
|
||||||
|
public fun build(): JvmPluginDescription =
|
||||||
|
SimpleJvmPluginDescription(name, version, id, author, info, dependencies, kind)
|
||||||
|
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
@DslMarker
|
||||||
|
private annotation class ILoveKuriyamaMiraiForever // https://zh.moegirl.org.cn/zh-cn/%E6%A0%97%E5%B1%B1%E6%9C%AA%E6%9D%A5
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @constructor 推荐使用带名称的参数, 而不要按位置摆放.
|
||||||
|
*
|
||||||
* @see JvmPluginDescription
|
* @see JvmPluginDescription
|
||||||
*/
|
*/
|
||||||
|
@Deprecated(
|
||||||
|
"""
|
||||||
|
将在 1.0-RC 删除. 请使用 JvmPluginDescription.
|
||||||
|
""",
|
||||||
|
replaceWith = ReplaceWith(
|
||||||
|
"JvmPluginDescription",
|
||||||
|
"net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription"
|
||||||
|
),
|
||||||
|
level = DeprecationLevel.ERROR
|
||||||
|
)
|
||||||
public data class SimpleJvmPluginDescription
|
public data class SimpleJvmPluginDescription
|
||||||
|
@Deprecated(
|
||||||
|
"""
|
||||||
|
构造器不稳定, 将在 1.0-RC 删除. 请使用 JvmPluginDescriptionBuilder.
|
||||||
|
""",
|
||||||
|
replaceWith = ReplaceWith(
|
||||||
|
"JvmPluginDescription(name, version) {}",
|
||||||
|
"net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription.Companion.invoke"
|
||||||
|
),
|
||||||
|
level = DeprecationLevel.ERROR
|
||||||
|
)
|
||||||
@JvmOverloads public constructor(
|
@JvmOverloads public constructor(
|
||||||
public override val name: String,
|
public override val name: String,
|
||||||
public override val version: Semver,
|
public override val version: Semver,
|
||||||
|
public override val id: String = name,
|
||||||
public override val author: String = "",
|
public override val author: String = "",
|
||||||
public override val info: String = "",
|
public override val info: String = "",
|
||||||
public override val dependencies: List<PluginDependency> = listOf(),
|
public override val dependencies: Set<PluginDependency> = setOf(),
|
||||||
public override val kind: PluginKind = PluginKind.NORMAL,
|
public override val kind: PluginKind = PluginKind.NORMAL,
|
||||||
) : JvmPluginDescription {
|
) : JvmPluginDescription {
|
||||||
|
|
||||||
|
@Deprecated(
|
||||||
|
"""
|
||||||
|
构造器不稳定, 将在 1.0-RC 删除. 请使用 JvmPluginDescriptionBuilder.
|
||||||
|
""",
|
||||||
|
replaceWith = ReplaceWith(
|
||||||
|
"JvmPluginDescription.invoke(name, version) {}",
|
||||||
|
"net.mamoe.mirai.console.plugin.jvm.JvmPluginDescription.Companion.invoke"
|
||||||
|
),
|
||||||
|
level = DeprecationLevel.ERROR
|
||||||
|
)
|
||||||
|
@Suppress("DEPRECATION_ERROR")
|
||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
public constructor(
|
public constructor(
|
||||||
name: String,
|
name: String,
|
||||||
version: String,
|
version: String,
|
||||||
|
id: String = name,
|
||||||
author: String = "",
|
author: String = "",
|
||||||
info: String = "",
|
info: String = "",
|
||||||
dependencies: List<PluginDependency> = listOf(),
|
dependencies: Set<PluginDependency> = setOf(),
|
||||||
kind: PluginKind = PluginKind.NORMAL,
|
kind: PluginKind = PluginKind.NORMAL,
|
||||||
) : this(name, Semver(version, Semver.SemverType.LOOSE), author, info, dependencies, kind)
|
) : this(name, Semver(version, Semver.SemverType.LOOSE), id, author, info, dependencies, kind)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
require(!name.contains(':')) { "':' is forbidden in plugin name" }
|
require(!name.contains(':')) { "':' is forbidden in plugin name" }
|
||||||
@ -59,15 +231,17 @@ public data class SimpleJvmPluginDescription
|
|||||||
),
|
),
|
||||||
level = DeprecationLevel.WARNING
|
level = DeprecationLevel.WARNING
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@LowPriorityInOverloadResolution
|
||||||
|
@Suppress("DEPRECATION_ERROR", "FunctionName")
|
||||||
public fun JvmPluginDescription(
|
public fun JvmPluginDescription(
|
||||||
name: String,
|
name: String,
|
||||||
version: Semver,
|
version: Semver,
|
||||||
|
id: String = name,
|
||||||
author: String = "",
|
author: String = "",
|
||||||
info: String = "",
|
info: String = "",
|
||||||
dependencies: List<PluginDependency> = listOf(),
|
dependencies: Set<PluginDependency> = setOf(),
|
||||||
kind: PluginKind = PluginKind.NORMAL
|
kind: PluginKind = PluginKind.NORMAL
|
||||||
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, author, info, dependencies, kind)
|
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, kind)
|
||||||
|
|
||||||
@Deprecated(
|
@Deprecated(
|
||||||
"JvmPluginDescription 没有构造器. 请使用 SimpleJvmPluginDescription.",
|
"JvmPluginDescription 没有构造器. 请使用 SimpleJvmPluginDescription.",
|
||||||
@ -77,12 +251,14 @@ public fun JvmPluginDescription(
|
|||||||
),
|
),
|
||||||
level = DeprecationLevel.WARNING
|
level = DeprecationLevel.WARNING
|
||||||
)
|
)
|
||||||
@Suppress("FunctionName")
|
@LowPriorityInOverloadResolution
|
||||||
|
@Suppress("DEPRECATION_ERROR", "FunctionName")
|
||||||
public fun JvmPluginDescription(
|
public fun JvmPluginDescription(
|
||||||
name: String,
|
name: String,
|
||||||
version: String,
|
version: String,
|
||||||
|
id: String = name,
|
||||||
author: String = "",
|
author: String = "",
|
||||||
info: String = "",
|
info: String = "",
|
||||||
dependencies: List<PluginDependency> = listOf(),
|
dependencies: Set<PluginDependency> = setOf(),
|
||||||
kind: PluginKind = PluginKind.NORMAL
|
kind: PluginKind = PluginKind.NORMAL
|
||||||
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, author, info, dependencies, kind)
|
): JvmPluginDescription = SimpleJvmPluginDescription(name, version, id, author, info, dependencies, kind)
|
||||||
|
@ -1,36 +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("NOTHING_TO_INLINE")
|
|
||||||
@file:JvmMultifileClass
|
|
||||||
@file:JvmName("ConsoleUtils")
|
|
||||||
|
|
||||||
package net.mamoe.mirai.console.util
|
|
||||||
|
|
||||||
import net.mamoe.mirai.Bot
|
|
||||||
import net.mamoe.mirai.console.internal.data.builtins.BotManagerImpl
|
|
||||||
import net.mamoe.mirai.contact.User
|
|
||||||
|
|
||||||
public interface BotManager {
|
|
||||||
/**
|
|
||||||
* 判断此用户是否为 console 管理员
|
|
||||||
*/
|
|
||||||
public val User.isManager: Boolean
|
|
||||||
public val Bot.managers: List<Long>
|
|
||||||
|
|
||||||
public fun Bot.removeManager(id: Long): Boolean
|
|
||||||
public fun Bot.addManager(id: Long): Boolean
|
|
||||||
|
|
||||||
public companion object INSTANCE : BotManager { // kotlin import handler doesn't recognize delegation.
|
|
||||||
override fun Bot.addManager(id: Long): Boolean = BotManagerImpl.run { addManager(id) }
|
|
||||||
override fun Bot.removeManager(id: Long): Boolean = BotManagerImpl.run { removeManager(id) }
|
|
||||||
override val User.isManager: Boolean get() = BotManagerImpl.run { isManager }
|
|
||||||
override val Bot.managers: List<Long> get() = BotManagerImpl.run { managers }
|
|
||||||
}
|
|
||||||
}
|
|
@ -10,8 +10,8 @@
|
|||||||
package net.mamoe.mirai.console.data
|
package net.mamoe.mirai.console.data
|
||||||
|
|
||||||
import kotlinx.serialization.json.Json
|
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.plugin.jvm.KotlinPlugin
|
||||||
import net.mamoe.mirai.console.plugin.jvm.SimpleJvmPluginDescription
|
|
||||||
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
import net.mamoe.mirai.console.util.ConsoleInternalAPI
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -21,7 +21,7 @@ import kotlin.test.assertSame
|
|||||||
internal class PluginDataTest {
|
internal class PluginDataTest {
|
||||||
|
|
||||||
object MyPlugin : KotlinPlugin(
|
object MyPlugin : KotlinPlugin(
|
||||||
SimpleJvmPluginDescription(
|
JvmPluginDescription(
|
||||||
"1", "2"
|
"1", "2"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user