mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-08 17:20:11 +08:00
Fix build
This commit is contained in:
parent
7dfd2fd5c9
commit
e53363482d
@ -8,6 +8,7 @@ import kotlinx.coroutines.CoroutineScope;
|
|||||||
import kotlinx.coroutines.CoroutineStart;
|
import kotlinx.coroutines.CoroutineStart;
|
||||||
import kotlinx.coroutines.future.FutureKt;
|
import kotlinx.coroutines.future.FutureKt;
|
||||||
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
|
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
|
||||||
|
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI;
|
||||||
import net.mamoe.mirai.message.data.Message;
|
import net.mamoe.mirai.message.data.Message;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@ -152,6 +153,7 @@ public final class JCommandManager {
|
|||||||
* @return 执行结果
|
* @return 执行结果
|
||||||
* @see #executeCommandDetailedAsync(CoroutineScope, CommandSender, Object...)
|
* @see #executeCommandDetailedAsync(CoroutineScope, CommandSender, Object...)
|
||||||
*/
|
*/
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CommandExecuteResult executeCommandDetailed(final @NotNull CommandSender sender, final @NotNull Object... args) throws InterruptedException {
|
public static CommandExecuteResult executeCommandDetailed(final @NotNull CommandSender sender, final @NotNull Object... args) throws InterruptedException {
|
||||||
Objects.requireNonNull(sender, "sender");
|
Objects.requireNonNull(sender, "sender");
|
||||||
@ -171,6 +173,7 @@ public final class JCommandManager {
|
|||||||
* @return 执行结果
|
* @return 执行结果
|
||||||
* @see #executeCommandDetailed(CommandSender, Object...)
|
* @see #executeCommandDetailed(CommandSender, Object...)
|
||||||
*/
|
*/
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
@NotNull
|
@NotNull
|
||||||
public static CompletableFuture<@NotNull CommandExecuteResult>
|
public static CompletableFuture<@NotNull CommandExecuteResult>
|
||||||
executeCommandDetailedAsync(final @NotNull CoroutineScope scope, final @NotNull CommandSender sender, final @NotNull Object... args) {
|
executeCommandDetailedAsync(final @NotNull CoroutineScope scope, final @NotNull CommandSender sender, final @NotNull Object... args) {
|
||||||
|
@ -20,6 +20,7 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.Job
|
import kotlinx.coroutines.Job
|
||||||
import net.mamoe.mirai.console.command.internal.*
|
import net.mamoe.mirai.console.command.internal.*
|
||||||
import net.mamoe.mirai.console.plugin.Plugin
|
import net.mamoe.mirai.console.plugin.Plugin
|
||||||
|
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||||
import net.mamoe.mirai.message.data.Message
|
import net.mamoe.mirai.message.data.Message
|
||||||
import net.mamoe.mirai.message.data.MessageChain
|
import net.mamoe.mirai.message.data.MessageChain
|
||||||
|
|
||||||
@ -229,6 +230,7 @@ public suspend fun Command.execute(sender: CommandSender, vararg args: Any, chec
|
|||||||
*
|
*
|
||||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||||
*/
|
*/
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
||||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||||
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
||||||
@ -243,6 +245,7 @@ public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): C
|
|||||||
*
|
*
|
||||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||||
*/
|
*/
|
||||||
|
@ConsoleExperimentalAPI
|
||||||
public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
||||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||||
return executeCommandDetailedInternal(messages, messages[0].toString())
|
return executeCommandDetailedInternal(messages, messages[0].toString())
|
||||||
|
@ -63,7 +63,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
|||||||
DefaultSubCommandDescriptor(
|
DefaultSubCommandDescriptor(
|
||||||
"",
|
"",
|
||||||
permission,
|
permission,
|
||||||
onCommand = block2 { sender: CommandSender, args: Array<out Any> ->
|
onCommand = { sender: CommandSender, args: Array<out Any> ->
|
||||||
sender.onDefault(args)
|
sender.onDefault(args)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@ -292,7 +292,7 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
|||||||
params,
|
params,
|
||||||
subDescription,
|
subDescription,
|
||||||
overridePermission?.value?.getInstance() ?: permission,
|
overridePermission?.value?.getInstance() ?: permission,
|
||||||
onCommand = block { sender: CommandSender, args: Array<out Any> ->
|
onCommand = { sender: CommandSender, args: Array<out Any> ->
|
||||||
val result = if (notStatic) {
|
val result = if (notStatic) {
|
||||||
if (hasSenderParam) {
|
if (hasSenderParam) {
|
||||||
function.isSuspend
|
function.isSuspend
|
||||||
@ -311,13 +311,4 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
|||||||
context = context,
|
context = context,
|
||||||
usage = buildUsage.toString()
|
usage = buildUsage.toString()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun block(block: suspend (CommandSender, Array<out Any>) -> Boolean): suspend (CommandSender, Array<out Any>) -> Boolean {
|
|
||||||
return block
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun block2(block: suspend (CommandSender, Array<out Any>) -> Unit): suspend (CommandSender, Array<out Any>) -> Unit {
|
|
||||||
return block
|
|
||||||
}
|
|
@ -11,22 +11,20 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.plugin.center
|
package net.mamoe.mirai.console.plugin.center
|
||||||
|
|
||||||
import io.ktor.client.HttpClient
|
import io.ktor.client.*
|
||||||
import io.ktor.client.engine.cio.CIO
|
import io.ktor.client.engine.cio.*
|
||||||
import io.ktor.client.request.get
|
import io.ktor.client.request.*
|
||||||
import io.ktor.util.KtorExperimentalAPI
|
import io.ktor.util.*
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.UnstableDefault
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
|
||||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||||
import net.mamoe.mirai.console.utils.retryCatching
|
import net.mamoe.mirai.console.utils.retryCatching
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@OptIn(UnstableDefault::class)
|
internal val json = Json {
|
||||||
internal val json = runCatching {
|
isLenient = true
|
||||||
Json(JsonConfiguration(isLenient = true, ignoreUnknownKeys = true))
|
ignoreUnknownKeys = true
|
||||||
}.getOrElse { Json(JsonConfiguration.Stable) }
|
}
|
||||||
|
|
||||||
@OptIn(KtorExperimentalAPI::class)
|
@OptIn(KtorExperimentalAPI::class)
|
||||||
internal val Http = HttpClient(CIO)
|
internal val Http = HttpClient(CIO)
|
||||||
@ -64,7 +62,7 @@ internal object CuiPluginCenter : PluginCenter {
|
|||||||
}.getOrElse { return null }
|
}.getOrElse { return null }
|
||||||
if (result == "err:not found") return null
|
if (result == "err:not found") return null
|
||||||
|
|
||||||
return json.parse(PluginCenter.PluginInfo.serializer(), result)
|
return json.decodeFromString(PluginCenter.PluginInfo.serializer(), result)
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun refresh() {
|
override suspend fun refresh() {
|
||||||
@ -75,7 +73,7 @@ internal object CuiPluginCenter : PluginCenter {
|
|||||||
val result: List<PluginCenter.PluginInsight>
|
val result: List<PluginCenter.PluginInsight>
|
||||||
)
|
)
|
||||||
|
|
||||||
val result = json.parse(Result.serializer(), Http.get("https://miraiapi.jasonczc.cn/getPluginList"))
|
val result = json.decodeFromString(Result.serializer(), Http.get("https://miraiapi.jasonczc.cn/getPluginList"))
|
||||||
|
|
||||||
check(result.success) { "Failed to fetch plugin list from Cui Cloud" }
|
check(result.success) { "Failed to fetch plugin list from Cui Cloud" }
|
||||||
plugins = result.result
|
plugins = result.result
|
||||||
|
@ -69,25 +69,25 @@ public interface SerializerAwareValue<T> : Value<T> {
|
|||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||||
public fun <T> SerializerAwareValue<T>.serialize(format: StringFormat): String {
|
public fun <T> SerializerAwareValue<T>.serialize(format: StringFormat): String {
|
||||||
return format.stringify(this.serializer, Unit)
|
return format.encodeToString(this.serializer, Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||||
public fun <T> SerializerAwareValue<T>.serialize(format: BinaryFormat): ByteArray {
|
public fun <T> SerializerAwareValue<T>.serialize(format: BinaryFormat): ByteArray {
|
||||||
return format.dump(this.serializer, Unit)
|
return format.encodeToByteArray(this.serializer, Unit)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||||
public fun <T> SerializerAwareValue<T>.deserialize(format: StringFormat, value: String) {
|
public fun <T> SerializerAwareValue<T>.deserialize(format: StringFormat, value: String) {
|
||||||
format.parse(this.serializer, value)
|
format.decodeFromString(this.serializer, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||||
public fun <T> SerializerAwareValue<T>.deserialize(format: BinaryFormat, value: ByteArray) {
|
public fun <T> SerializerAwareValue<T>.deserialize(format: BinaryFormat, value: ByteArray) {
|
||||||
format.load(this.serializer, value)
|
format.decodeFromByteArray(this.serializer, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,18 +7,15 @@
|
|||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@file:Suppress("NOTHING_TO_INLINE")
|
@file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||||
|
|
||||||
package net.mamoe.mirai.console.setting.internal
|
package net.mamoe.mirai.console.setting.internal
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.builtins.*
|
|
||||||
import net.mamoe.mirai.console.setting.SerializableValue.Companion.serializableValueWith
|
import net.mamoe.mirai.console.setting.SerializableValue.Companion.serializableValueWith
|
||||||
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
||||||
import net.mamoe.mirai.console.setting.Setting
|
import net.mamoe.mirai.console.setting.Setting
|
||||||
import net.mamoe.mirai.console.setting.valueFromKType
|
import net.mamoe.mirai.console.setting.valueFromKType
|
||||||
import net.mamoe.yamlkt.YamlDynamicSerializer
|
|
||||||
import net.mamoe.yamlkt.YamlNullableDynamicSerializer
|
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KType
|
import kotlin.reflect.KType
|
||||||
import kotlin.reflect.full.createInstance as createInstanceKotlin
|
import kotlin.reflect.full.createInstance as createInstanceKotlin
|
||||||
@ -142,63 +139,3 @@ internal fun KClass<*>.isPrimitiveOrBuiltInSerializableValue(): Boolean {
|
|||||||
@PublishedApi
|
@PublishedApi
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
internal inline fun <R> Any.cast(): R = this as R
|
internal inline fun <R> Any.cast(): R = this as R
|
||||||
|
|
||||||
/**
|
|
||||||
* Copied from kotlinx.serialization, modifications are marked with "/* mamoe modify */"
|
|
||||||
* Copyright 2017-2020 JetBrains s.r.o.
|
|
||||||
*/
|
|
||||||
@Suppress(
|
|
||||||
"UNCHECKED_CAST",
|
|
||||||
"NO_REFLECTION_IN_CLASS_PATH",
|
|
||||||
"UNSUPPORTED",
|
|
||||||
"INVISIBLE_MEMBER",
|
|
||||||
"INVISIBLE_REFERENCE",
|
|
||||||
"IMPLICIT_CAST_TO_ANY"
|
|
||||||
)
|
|
||||||
@OptIn(ImplicitReflectionSerializer::class)
|
|
||||||
internal fun serializerMirai(type: KType): KSerializer<Any?> {
|
|
||||||
fun serializerByKTypeImpl(type: KType): KSerializer<Any> {
|
|
||||||
val rootClass = when (val t = type.classifier) {
|
|
||||||
is KClass<*> -> t
|
|
||||||
else -> error("Only KClass supported as classifier, got $t")
|
|
||||||
} as KClass<Any>
|
|
||||||
|
|
||||||
val typeArguments = type.arguments
|
|
||||||
.map { requireNotNull(it.type) { "Star projections are not allowed, had $it instead" } }
|
|
||||||
return when {
|
|
||||||
typeArguments.isEmpty() -> rootClass.serializer()
|
|
||||||
else -> {
|
|
||||||
val serializers = typeArguments
|
|
||||||
.map(::serializer)
|
|
||||||
// Array is not supported, see KT-32839
|
|
||||||
when (rootClass) {
|
|
||||||
List::class, MutableList::class, ArrayList::class -> ListSerializer(serializers[0])
|
|
||||||
HashSet::class -> SetSerializer(serializers[0])
|
|
||||||
Set::class, MutableSet::class, LinkedHashSet::class -> SetSerializer(serializers[0])
|
|
||||||
HashMap::class -> MapSerializer(serializers[0], serializers[1])
|
|
||||||
Map::class, MutableMap::class, LinkedHashMap::class -> MapSerializer(serializers[0], serializers[1])
|
|
||||||
Map.Entry::class -> MapEntrySerializer(serializers[0], serializers[1])
|
|
||||||
Pair::class -> PairSerializer(serializers[0], serializers[1])
|
|
||||||
Triple::class -> TripleSerializer(serializers[0], serializers[1], serializers[2])
|
|
||||||
/* mamoe modify */ Any::class -> if (type.isMarkedNullable) YamlNullableDynamicSerializer else YamlDynamicSerializer
|
|
||||||
else -> {
|
|
||||||
if (isReferenceArray(type, rootClass)) {
|
|
||||||
@Suppress("RemoveExplicitTypeArguments")
|
|
||||||
return ArraySerializer<Any, Any?>(
|
|
||||||
typeArguments[0].classifier as KClass<Any>,
|
|
||||||
serializers[0]
|
|
||||||
).cast()
|
|
||||||
}
|
|
||||||
requireNotNull(rootClass.constructSerializerForGivenTypeArgs(*serializers.toTypedArray())) {
|
|
||||||
"Can't find a method to construct serializer for type ${rootClass.simpleName()}. " +
|
|
||||||
"Make sure this class is marked as @Serializable or provide serializer explicitly."
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}.cast()
|
|
||||||
}
|
|
||||||
|
|
||||||
val result = serializerByKTypeImpl(type)
|
|
||||||
return if (type.isMarkedNullable) result.nullable else result.cast()
|
|
||||||
}
|
|
||||||
|
@ -11,9 +11,14 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.setting.internal
|
package net.mamoe.mirai.console.setting.internal
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
import kotlinx.serialization.builtins.MapSerializer
|
import kotlinx.serialization.builtins.MapSerializer
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.CompositeDecoder
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
||||||
import net.mamoe.mirai.console.setting.Setting
|
import net.mamoe.mirai.console.setting.Setting
|
||||||
import net.mamoe.mirai.console.setting.Value
|
import net.mamoe.mirai.console.setting.Value
|
||||||
@ -53,7 +58,7 @@ internal abstract class SettingImpl {
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun deserialize(decoder: Decoder) {
|
override fun deserialize(decoder: Decoder) {
|
||||||
val descriptor = descriptor
|
val descriptor = descriptor
|
||||||
with(decoder.beginStructure(descriptor, *settingUpdaterSerializerTypeArguments)) {
|
with(decoder.beginStructure(descriptor)) {
|
||||||
if (decodeSequentially()) {
|
if (decodeSequentially()) {
|
||||||
var index = 0
|
var index = 0
|
||||||
repeat(decodeCollectionSize(descriptor)) {
|
repeat(decodeCollectionSize(descriptor)) {
|
||||||
@ -70,7 +75,7 @@ internal abstract class SettingImpl {
|
|||||||
var serialName: String? = null
|
var serialName: String? = null
|
||||||
innerLoop@ while (true) {
|
innerLoop@ while (true) {
|
||||||
val index = decodeElementIndex(descriptor)
|
val index = decodeElementIndex(descriptor)
|
||||||
if (index == CompositeDecoder.READ_DONE) {
|
if (index == CompositeDecoder.DECODE_DONE) {
|
||||||
check(serialName == null) { "name must be null at this moment." }
|
check(serialName == null) { "name must be null at this moment." }
|
||||||
break@outerLoop
|
break@outerLoop
|
||||||
}
|
}
|
||||||
@ -102,7 +107,7 @@ internal abstract class SettingImpl {
|
|||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
override fun serialize(encoder: Encoder, value: Unit) {
|
override fun serialize(encoder: Encoder, value: Unit) {
|
||||||
val descriptor = descriptor
|
val descriptor = descriptor
|
||||||
with(encoder.beginCollection(descriptor, valueNodes.size, *settingUpdaterSerializerTypeArguments)) {
|
with(encoder.beginCollection(descriptor, valueNodes.size)) {
|
||||||
var index = 0
|
var index = 0
|
||||||
|
|
||||||
// val vSerializer = settingUpdaterSerializerTypeArguments[1] as KSerializer<Any?>
|
// val vSerializer = settingUpdaterSerializerTypeArguments[1] as KSerializer<Any?>
|
||||||
|
@ -9,11 +9,11 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.setting.internal
|
package net.mamoe.mirai.console.setting.internal
|
||||||
|
|
||||||
import kotlinx.serialization.Decoder
|
|
||||||
import kotlinx.serialization.Encoder
|
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.SerialDescriptor
|
|
||||||
import kotlinx.serialization.builtins.serializer
|
import kotlinx.serialization.builtins.serializer
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import net.mamoe.mirai.console.setting.*
|
import net.mamoe.mirai.console.setting.*
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,6 +98,7 @@ internal abstract class ShortValueImpl : ShortValue, SerializerAwareValue<Short>
|
|||||||
else value.hashCode() * 31
|
else value.hashCode() * 31
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit>, AbstractValueImpl<Int> {
|
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit>, AbstractValueImpl<Int> {
|
||||||
constructor()
|
constructor()
|
||||||
constructor(default: Int) {
|
constructor(default: Int) {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.setting.internal
|
package net.mamoe.mirai.console.setting.internal
|
||||||
|
|
||||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
import kotlinx.serialization.UnsafeSerializationApi
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
import net.mamoe.yamlkt.Yaml
|
import net.mamoe.yamlkt.Yaml
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
@ -452,7 +452,7 @@ internal inline fun <T> MutableSet<T>.observable(crossinline onChanged: () -> Un
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@OptIn(ImplicitReflectionSerializer::class)
|
@OptIn(UnsafeSerializationApi::class)
|
||||||
internal fun <R : Any> Any.smartCastPrimitive(clazz: KClass<R>): R {
|
internal fun <R : Any> Any.smartCastPrimitive(clazz: KClass<R>): R {
|
||||||
kotlin.runCatching {
|
kotlin.runCatching {
|
||||||
return Yaml.default.parse(clazz.serializer(), this.toString())
|
return Yaml.default.parse(clazz.serializer(), this.toString())
|
||||||
|
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* 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.setting.internal
|
||||||
|
|
||||||
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.UnsafeSerializationApi
|
||||||
|
import kotlinx.serialization.builtins.*
|
||||||
|
import kotlinx.serialization.serializer
|
||||||
|
import net.mamoe.yamlkt.YamlDynamicSerializer
|
||||||
|
import net.mamoe.yamlkt.YamlNullableDynamicSerializer
|
||||||
|
import java.lang.reflect.Modifier
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
import kotlin.reflect.KType
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied from kotlinx.serialization, modifications are marked with "/* mamoe modify */"
|
||||||
|
* Copyright 2017-2020 JetBrains s.r.o.
|
||||||
|
*/
|
||||||
|
@OptIn(UnsafeSerializationApi::class)
|
||||||
|
@Suppress(
|
||||||
|
"UNCHECKED_CAST",
|
||||||
|
"NO_REFLECTION_IN_CLASS_PATH",
|
||||||
|
"UNSUPPORTED",
|
||||||
|
"INVISIBLE_MEMBER",
|
||||||
|
"INVISIBLE_REFERENCE",
|
||||||
|
"IMPLICIT_CAST_TO_ANY"
|
||||||
|
)
|
||||||
|
internal fun serializerMirai(type: KType): KSerializer<Any?> {
|
||||||
|
fun serializerByKTypeImpl(type: KType): KSerializer<Any> {
|
||||||
|
val rootClass = type.kclass()
|
||||||
|
|
||||||
|
val typeArguments = type.arguments
|
||||||
|
.map { requireNotNull(it.type) { "Star projections in type arguments are not allowed, but had $type" } }
|
||||||
|
return when {
|
||||||
|
typeArguments.isEmpty() -> rootClass.serializer()
|
||||||
|
else -> {
|
||||||
|
val serializers = typeArguments
|
||||||
|
.map(::serializer)
|
||||||
|
// Array is not supported, see KT-32839
|
||||||
|
when (rootClass) {
|
||||||
|
List::class, MutableList::class, ArrayList::class -> ListSerializer(serializers[0])
|
||||||
|
HashSet::class -> SetSerializer(serializers[0])
|
||||||
|
Set::class, MutableSet::class, LinkedHashSet::class -> SetSerializer(serializers[0])
|
||||||
|
HashMap::class -> MapSerializer(serializers[0], serializers[1])
|
||||||
|
Map::class, MutableMap::class, LinkedHashMap::class -> MapSerializer(serializers[0], serializers[1])
|
||||||
|
Map.Entry::class -> MapEntrySerializer(serializers[0], serializers[1])
|
||||||
|
Pair::class -> PairSerializer(serializers[0], serializers[1])
|
||||||
|
Triple::class -> TripleSerializer(serializers[0], serializers[1], serializers[2])
|
||||||
|
/* mamoe modify */ Any::class -> if (type.isMarkedNullable) YamlNullableDynamicSerializer else YamlDynamicSerializer
|
||||||
|
else -> {
|
||||||
|
if (isReferenceArray(rootClass)) {
|
||||||
|
return ArraySerializer(
|
||||||
|
typeArguments[0].classifier as KClass<Any>,
|
||||||
|
serializers[0]
|
||||||
|
).cast()
|
||||||
|
}
|
||||||
|
requireNotNull(rootClass.constructSerializerForGivenTypeArgs(*serializers.toTypedArray())) {
|
||||||
|
"Can't find a method to construct serializer for type ${rootClass.simpleName}. " +
|
||||||
|
"Make sure this class is marked as @Serializable or provide serializer explicitly."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.cast()
|
||||||
|
}
|
||||||
|
|
||||||
|
val result = serializerByKTypeImpl(type)
|
||||||
|
return if (type.isMarkedNullable) result.nullable else result.cast()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copied from kotlinx.serialization, modifications are marked with "/* mamoe modify */"
|
||||||
|
* Copyright 2017-2020 JetBrains s.r.o.
|
||||||
|
*/
|
||||||
|
@OptIn(UnsafeSerializationApi::class)
|
||||||
|
@Suppress(
|
||||||
|
"UNCHECKED_CAST",
|
||||||
|
"NO_REFLECTION_IN_CLASS_PATH",
|
||||||
|
"UNSUPPORTED",
|
||||||
|
"INVISIBLE_MEMBER",
|
||||||
|
"INVISIBLE_REFERENCE",
|
||||||
|
"IMPLICIT_CAST_TO_ANY"
|
||||||
|
)
|
||||||
|
private fun <T : Any> KClass<T>.constructSerializerForGivenTypeArgs(vararg args: KSerializer<Any?>): KSerializer<T>? {
|
||||||
|
val jClass = this.java
|
||||||
|
// Search for serializer defined on companion object.
|
||||||
|
val companion =
|
||||||
|
jClass.declaredFields.singleOrNull { it.name == "Companion" }?.apply { isAccessible = true }?.get(null)
|
||||||
|
if (companion != null) {
|
||||||
|
val serializer = companion.javaClass.methods
|
||||||
|
.find { method ->
|
||||||
|
method.name == "serializer" && method.parameterTypes.size == args.size && method.parameterTypes.all { it == KSerializer::class.java }
|
||||||
|
}
|
||||||
|
?.invoke(companion, *args) as? KSerializer<T>
|
||||||
|
if (serializer != null) return serializer
|
||||||
|
}
|
||||||
|
// Check whether it's serializable object
|
||||||
|
findObjectSerializer(jClass)?.let { return it }
|
||||||
|
// Search for default serializer if no serializer is defined in companion object.
|
||||||
|
return try {
|
||||||
|
jClass.declaredClasses.singleOrNull { it.simpleName == ("\$serializer") }
|
||||||
|
?.getField("INSTANCE")?.get(null) as? KSerializer<T>
|
||||||
|
} catch (e: NoSuchFieldException) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : Any> findObjectSerializer(jClass: Class<T>): KSerializer<T>? {
|
||||||
|
// Check it is an object without using kotlin-reflect
|
||||||
|
val field =
|
||||||
|
jClass.declaredFields.singleOrNull { it.name == "INSTANCE" && it.type == jClass && Modifier.isStatic(it.modifiers) }
|
||||||
|
?: return null
|
||||||
|
// Retrieve its instance and call serializer()
|
||||||
|
val instance = field.get(null)
|
||||||
|
val method =
|
||||||
|
jClass.methods.singleOrNull { it.name == "serializer" && it.parameters.isEmpty() && it.returnType == KSerializer::class.java }
|
||||||
|
?: return null
|
||||||
|
val result = method.invoke(instance)
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return result as? KSerializer<T>
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isReferenceArray(rootClass: KClass<Any>): Boolean = rootClass.java.isArray
|
||||||
|
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
private fun KType.kclass() = when (val t = classifier) {
|
||||||
|
is KClass<*> -> t
|
||||||
|
else -> error("Only KClass supported as classifier, got $t")
|
||||||
|
} as KClass<Any>
|
@ -9,7 +9,11 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.setting.internal
|
package net.mamoe.mirai.console.setting.internal
|
||||||
|
|
||||||
import kotlinx.serialization.*
|
import kotlinx.serialization.KSerializer
|
||||||
|
import kotlinx.serialization.SerialName
|
||||||
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
|
import kotlinx.serialization.encoding.Decoder
|
||||||
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
import kotlin.reflect.full.findAnnotation
|
import kotlin.reflect.full.findAnnotation
|
||||||
|
|
||||||
|
@ -9,9 +9,7 @@
|
|||||||
|
|
||||||
package net.mamoe.mirai.console.setting
|
package net.mamoe.mirai.console.setting
|
||||||
|
|
||||||
import kotlinx.serialization.UnstableDefault
|
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonConfiguration
|
|
||||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||||
import org.junit.jupiter.api.Test
|
import org.junit.jupiter.api.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
@ -34,20 +32,19 @@ internal class SettingTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(UnstableDefault::class)
|
private val jsonPrettyPrint = Json { prettyPrint = true }
|
||||||
private val jsonPrettyPrint = Json(JsonConfiguration(prettyPrint = true))
|
private val json = Json {}
|
||||||
private val json = Json(JsonConfiguration.Stable)
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testStringify() {
|
fun testStringify() {
|
||||||
val setting = MySetting()
|
val setting = MySetting()
|
||||||
|
|
||||||
var string = json.stringify(setting.updaterSerializer, Unit)
|
var string = json.encodeToString(setting.updaterSerializer, Unit)
|
||||||
assertEquals("""{"int":1,"map":{},"map2":{}}""", string)
|
assertEquals("""{"int":1,"map":{},"map2":{}}""", string)
|
||||||
|
|
||||||
setting.int = 2
|
setting.int = 2
|
||||||
|
|
||||||
string = json.stringify(setting.updaterSerializer, Unit)
|
string = json.encodeToString(setting.updaterSerializer, Unit)
|
||||||
assertEquals("""{"int":2,"map":{},"map2":{}}""", string)
|
assertEquals("""{"int":2,"map":{},"map2":{}}""", string)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,10 +54,10 @@ internal class SettingTest {
|
|||||||
|
|
||||||
assertEquals(1, setting.int)
|
assertEquals(1, setting.int)
|
||||||
|
|
||||||
json.parse(
|
json.decodeFromString(
|
||||||
setting.updaterSerializer, """
|
setting.updaterSerializer, """
|
||||||
{"int":3,"map":{},"map2":{}}
|
{"int":3,"map":{},"map2":{}}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(3, setting.int)
|
assertEquals(3, setting.int)
|
||||||
@ -77,10 +74,10 @@ internal class SettingTest {
|
|||||||
|
|
||||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||||
|
|
||||||
json.parse(
|
json.decodeFromString(
|
||||||
setting.updaterSerializer, """
|
setting.updaterSerializer, """
|
||||||
{"int":1,"map":{"t":"test"},"map2":{}}
|
{"int":1,"map":{"t":"test"},"map2":{}}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(mapOf("t" to "test").toString(), delegation().toString())
|
assertEquals(mapOf("t" to "test").toString(), delegation().toString())
|
||||||
@ -100,10 +97,10 @@ internal class SettingTest {
|
|||||||
|
|
||||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||||
|
|
||||||
json.parse(
|
json.decodeFromString(
|
||||||
setting.updaterSerializer, """
|
setting.updaterSerializer, """
|
||||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(mapOf("t" to mapOf("f" to "test")).toString(), delegation().toString())
|
assertEquals(mapOf("t" to mapOf("f" to "test")).toString(), delegation().toString())
|
||||||
@ -125,10 +122,10 @@ internal class SettingTest {
|
|||||||
|
|
||||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||||
|
|
||||||
json.parse(
|
json.decodeFromString(
|
||||||
setting.updaterSerializer, """
|
setting.updaterSerializer, """
|
||||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
)
|
)
|
||||||
|
|
||||||
assertEquals(mapOf("f" to "test").toString(), delegation().toString())
|
assertEquals(mapOf("f" to "test").toString(), delegation().toString())
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id("com.jfrog.bintray") version Versions.bintray apply false
|
id("com.jfrog.bintray") version Versions.bintray apply false
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.withType(JavaCompile::class.java) {
|
tasks.withType(JavaCompile::class.java) {
|
||||||
options.encoding = "UTF8"
|
options.encoding = "UTF8"
|
||||||
}
|
}
|
||||||
|
@ -1,211 +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
|
|
||||||
|
|
||||||
import kotlinx.coroutines.CoroutineScope
|
|
||||||
import kotlinx.io.charsets.Charset
|
|
||||||
import net.mamoe.mirai.Bot
|
|
||||||
import net.mamoe.mirai.console.command.CommandManager
|
|
||||||
import net.mamoe.mirai.console.command.DefaultCommands
|
|
||||||
import net.mamoe.mirai.console.plugins.PluginManager
|
|
||||||
import net.mamoe.mirai.console.utils.MiraiConsoleUI
|
|
||||||
import net.mamoe.mirai.utils.SimpleLogger.LogPriority
|
|
||||||
import net.mamoe.mirai.utils.WeakRef
|
|
||||||
import java.io.ByteArrayOutputStream
|
|
||||||
import java.io.PrintStream
|
|
||||||
import kotlin.coroutines.EmptyCoroutineContext
|
|
||||||
|
|
||||||
|
|
||||||
object MiraiConsole : CoroutineScope by CoroutineScope(EmptyCoroutineContext) {
|
|
||||||
/**
|
|
||||||
* 发布的版本名
|
|
||||||
*/
|
|
||||||
const val build = "Pkmon"
|
|
||||||
|
|
||||||
lateinit var version: String
|
|
||||||
internal set
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取从Console登陆上的Bot, Bots
|
|
||||||
* */
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
@Deprecated(
|
|
||||||
"use Bot.botInstances from mirai-core",
|
|
||||||
replaceWith = ReplaceWith("Bot.instances", "net.mamoe.mirai.Bot"),
|
|
||||||
level = DeprecationLevel.ERROR
|
|
||||||
)
|
|
||||||
val bots: List<WeakRef<Bot>>
|
|
||||||
@Suppress("DEPRECATION_ERROR")
|
|
||||||
get() = Bot.instances
|
|
||||||
|
|
||||||
fun getBotOrNull(uin: Long): Bot? {
|
|
||||||
return Bot.botInstances.firstOrNull { it.id == uin }
|
|
||||||
}
|
|
||||||
|
|
||||||
class BotNotFoundException(uin: Long) : Exception("Bot $uin Not Found")
|
|
||||||
|
|
||||||
fun getBotOrThrow(uin: Long): Bot {
|
|
||||||
return Bot.botInstances.firstOrNull { it.id == uin } ?: throw BotNotFoundException(uin)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 与前端交互所使用的Logger
|
|
||||||
*/
|
|
||||||
internal var logger = MiraiConsoleLogger
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Console运行路径
|
|
||||||
*/
|
|
||||||
lateinit var path: String
|
|
||||||
internal set
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Console前端接口
|
|
||||||
*/
|
|
||||||
lateinit var frontEnd: MiraiConsoleUI
|
|
||||||
internal set
|
|
||||||
|
|
||||||
|
|
||||||
private var started = false
|
|
||||||
|
|
||||||
|
|
||||||
@Deprecated("for binary compatibility", level = DeprecationLevel.HIDDEN)
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
@JvmSynthetic
|
|
||||||
@JvmStatic
|
|
||||||
fun /* synthetic */`start$default`(
|
|
||||||
miraiConsole: MiraiConsole,
|
|
||||||
miraiConsoleUI: MiraiConsoleUI?,
|
|
||||||
string: String?,
|
|
||||||
string2: String?,
|
|
||||||
n: Int,
|
|
||||||
@Suppress("UNUSED_PARAMETER") `object`: Any?
|
|
||||||
) {
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
var string = string
|
|
||||||
|
|
||||||
@Suppress("NAME_SHADOWING")
|
|
||||||
var string2 = string2
|
|
||||||
if (n and 2 != 0) {
|
|
||||||
string = "0.0.0"
|
|
||||||
}
|
|
||||||
if (n and 4 != 0) {
|
|
||||||
string2 = "0.0.0"
|
|
||||||
}
|
|
||||||
miraiConsole.start(miraiConsoleUI!!, string!!, string2!!)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 启动Console
|
|
||||||
*/
|
|
||||||
@JvmOverloads
|
|
||||||
fun start(
|
|
||||||
frontEnd: MiraiConsoleUI,
|
|
||||||
coreVersion: String = "0.0.0",
|
|
||||||
consoleVersion: String = "0.0.0",
|
|
||||||
path: String = System.getProperty("user.dir")
|
|
||||||
) {
|
|
||||||
if (started) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
started = true
|
|
||||||
this.path = path
|
|
||||||
/* 初始化前端 */
|
|
||||||
this.version = consoleVersion
|
|
||||||
this.frontEnd = frontEnd
|
|
||||||
this.frontEnd.pushVersion(consoleVersion, build, coreVersion)
|
|
||||||
logger("Mirai-console now running under $path")
|
|
||||||
logger("Get news in github: https://github.com/mamoe/mirai")
|
|
||||||
logger("Mirai为开源项目,请自觉遵守开源项目协议")
|
|
||||||
logger("Powered by Mamoe Technologies and contributors")
|
|
||||||
|
|
||||||
/* 依次启用功能 */
|
|
||||||
DefaultCommands()
|
|
||||||
PluginManager.loadPlugins()
|
|
||||||
CommandManager.start()
|
|
||||||
|
|
||||||
/* 通知启动完成 */
|
|
||||||
logger("Mirai-console 启动完成")
|
|
||||||
logger("\"login qqnumber qqpassword \" to login a bot")
|
|
||||||
logger("\"login qq号 qq密码 \" 来登录一个BOT")
|
|
||||||
|
|
||||||
/* 尝试从系统配置自动登录 */
|
|
||||||
DefaultCommands.tryLoginAuto()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 关闭 Console
|
|
||||||
*/
|
|
||||||
fun stop() {
|
|
||||||
PluginManager.disablePlugins()
|
|
||||||
CommandManager.cancel()
|
|
||||||
try {
|
|
||||||
Bot.botInstances.forEach {
|
|
||||||
it.close()
|
|
||||||
}
|
|
||||||
} catch (ignored: Exception) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
internal object MiraiConsoleLogger {
|
|
||||||
operator fun invoke(any: Any?) {
|
|
||||||
invoke(
|
|
||||||
"[Mirai ${MiraiConsole.version} ${MiraiConsole.build}]",
|
|
||||||
0L,
|
|
||||||
any
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun invoke(e: Throwable?) {
|
|
||||||
invoke(
|
|
||||||
"[Mirai ${MiraiConsole.version} ${MiraiConsole.build}]",
|
|
||||||
0L,
|
|
||||||
e
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, any: Any? = null) {
|
|
||||||
if (any != null) {
|
|
||||||
MiraiConsole.frontEnd.pushLog(priority, identityStr, identity, "$any")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun invoke(priority: LogPriority, identityStr: String, identity: Long, e: Throwable? = null) {
|
|
||||||
if (e != null) {
|
|
||||||
MiraiConsole.frontEnd.pushLog(priority, identityStr, identity, e.stacktraceString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 设置默认的pushLog输出为 INFO 类型
|
|
||||||
operator fun invoke(identityStr: String, identity: Long, any: Any? = null) {
|
|
||||||
if (any != null) {
|
|
||||||
MiraiConsole.frontEnd.pushLog(LogPriority.INFO, identityStr, identity, "$any")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
operator fun invoke(identityStr: String, identity: Long, e: Throwable? = null) {
|
|
||||||
if (e != null) {
|
|
||||||
MiraiConsole.frontEnd.pushLog(LogPriority.INFO, identityStr, identity, e.stacktraceString)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal val Throwable.stacktraceString: String
|
|
||||||
get() =
|
|
||||||
ByteArrayOutputStream().apply {
|
|
||||||
printStackTrace(PrintStream(this))
|
|
||||||
}.use { it.toByteArray().encodeToString() }
|
|
||||||
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
|
||||||
internal inline fun ByteArray.encodeToString(charset: Charset = Charsets.UTF_8): String =
|
|
||||||
kotlinx.io.core.String(this, charset = charset)
|
|
@ -1,132 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2020 Mamoe Technologies and contributors.
|
|
||||||
*
|
|
||||||
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
|
|
||||||
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
|
|
||||||
*
|
|
||||||
* https://github.com/mamoe/mirai/blob/master/LICENSE
|
|
||||||
*/
|
|
||||||
|
|
||||||
@file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE", "unused", "MemberVisibilityCanBePrivate")
|
|
||||||
|
|
||||||
package net.mamoe.mirai.console.command
|
|
||||||
|
|
||||||
import net.mamoe.mirai.Bot
|
|
||||||
import net.mamoe.mirai.console.command.AbstractCommandParserContext.Node
|
|
||||||
import net.mamoe.mirai.contact.Friend
|
|
||||||
import net.mamoe.mirai.contact.Group
|
|
||||||
import net.mamoe.mirai.contact.Member
|
|
||||||
import kotlin.internal.LowPriorityInOverloadResolution
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [KClass] 到 [CommandArgParser] 的匹配
|
|
||||||
*/
|
|
||||||
interface CommandParserContext {
|
|
||||||
operator fun <T : Any> get(klass: KClass<T>): CommandArgParser<T>?
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 内建的默认 [CommandArgParser]
|
|
||||||
*/
|
|
||||||
object Builtins : CommandParserContext by (CommandParserContext {
|
|
||||||
Int::class with IntArgParser
|
|
||||||
Byte::class with ByteArgParser
|
|
||||||
Short::class with ShortArgParser
|
|
||||||
Boolean::class with BooleanArgParser
|
|
||||||
String::class with StringArgParser
|
|
||||||
Long::class with LongArgParser
|
|
||||||
Double::class with DoubleArgParser
|
|
||||||
Float::class with FloatArgParser
|
|
||||||
|
|
||||||
Member::class with ExistMemberArgParser
|
|
||||||
Group::class with ExistGroupArgParser
|
|
||||||
Friend::class with ExistFriendArgParser
|
|
||||||
Bot::class with ExistBotArgParser
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <T : Any> CommandParserContext.parserFor(param: CommandParam<T>): CommandArgParser<T>? = this[param.type]
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 合并两个 [CommandParserContext], [replacer] 将会替换 [this] 中重复的 parser.
|
|
||||||
*/
|
|
||||||
operator fun CommandParserContext.plus(replacer: CommandParserContext): CommandParserContext {
|
|
||||||
return object : CommandParserContext {
|
|
||||||
override fun <T : Any> get(klass: KClass<T>): CommandArgParser<T>? = replacer[klass] ?: this@plus[klass]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
open class AbstractCommandParserContext(val list: List<Node<*>>) : CommandParserContext {
|
|
||||||
class Node<T : Any>(
|
|
||||||
val klass: KClass<T>,
|
|
||||||
val parser: CommandArgParser<T>
|
|
||||||
)
|
|
||||||
|
|
||||||
override fun <T : Any> get(klass: KClass<T>): CommandArgParser<T>? =
|
|
||||||
this.list.firstOrNull { it.klass == klass }?.parser as CommandArgParser<T>?
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建一个 [CommandParserContext].
|
|
||||||
*
|
|
||||||
* ```
|
|
||||||
* CommandParserContext {
|
|
||||||
* Int::class with IntArgParser
|
|
||||||
* Member::class with ExistMemberArgParser
|
|
||||||
* Group::class with { s: String, sender: CommandSender ->
|
|
||||||
* Bot.getInstance(s.toLong()).getGroup(s.toLong())
|
|
||||||
* }
|
|
||||||
* Bot::class with { s: String ->
|
|
||||||
* Bot.getInstance(s.toLong())
|
|
||||||
* }
|
|
||||||
* }
|
|
||||||
* ```
|
|
||||||
*/
|
|
||||||
@Suppress("FunctionName")
|
|
||||||
@JvmSynthetic
|
|
||||||
inline fun CommandParserContext(block: CommandParserContextBuilder.() -> Unit): CommandParserContext {
|
|
||||||
return AbstractCommandParserContext(
|
|
||||||
CommandParserContextBuilder().apply(block).distinctByReversed { it.klass })
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @see CommandParserContext
|
|
||||||
*/
|
|
||||||
class CommandParserContextBuilder : MutableList<Node<*>> by mutableListOf() {
|
|
||||||
@JvmName("add")
|
|
||||||
inline infix fun <T : Any> KClass<T>.with(parser: CommandArgParser<T>): Node<*> =
|
|
||||||
Node(this, parser)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加一个指令解析器
|
|
||||||
*/
|
|
||||||
@JvmSynthetic
|
|
||||||
@LowPriorityInOverloadResolution
|
|
||||||
inline infix fun <T : Any> KClass<T>.with(
|
|
||||||
crossinline parser: CommandArgParser<T>.(s: String, sender: CommandSender) -> T
|
|
||||||
): Node<*> = Node(this, CommandArgParser(parser))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加一个指令解析器
|
|
||||||
*/
|
|
||||||
@JvmSynthetic
|
|
||||||
inline infix fun <T : Any> KClass<T>.with(
|
|
||||||
crossinline parser: CommandArgParser<T>.(s: String) -> T
|
|
||||||
): Node<*> = Node(this, CommandArgParser { s: String, _: CommandSender -> parser(s) })
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@PublishedApi
|
|
||||||
internal inline fun <T, K> Iterable<T>.distinctByReversed(selector: (T) -> K): List<T> {
|
|
||||||
val set = HashSet<K>()
|
|
||||||
val list = ArrayList<T>()
|
|
||||||
for (i in list.indices.reversed()) {
|
|
||||||
val element = list[i]
|
|
||||||
if (set.add(element.let(selector))) {
|
|
||||||
list.add(element)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return list
|
|
||||||
}
|
|
@ -1,21 +1,11 @@
|
|||||||
pluginManagement {
|
pluginManagement {
|
||||||
repositories {
|
repositories {
|
||||||
mavenLocal()
|
mavenLocal()
|
||||||
|
gradlePluginPortal()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
|
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
}
|
}
|
||||||
|
|
||||||
resolutionStrategy {
|
|
||||||
eachPlugin {
|
|
||||||
val version = requested.version
|
|
||||||
when (requested.id.id) {
|
|
||||||
"org.jetbrains.kotlin.jvm" -> useModule("org.jetbrains.kotlin:kotlin-gradle-plugin:${version}")
|
|
||||||
"org.jetbrains.kotlin.plugin.serialization" -> useModule("org.jetbrains.kotlin:kotlin-serialization:${version}")
|
|
||||||
"com.jfrog.bintray" -> useModule("com.jfrog.bintray.gradle:gradle-bintray-plugin:$version")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rootProject.name = "mirai-console"
|
rootProject.name = "mirai-console"
|
||||||
|
Loading…
Reference in New Issue
Block a user