mirror of
https://github.com/mamoe/mirai.git
synced 2025-01-07 16:40:43 +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.future.FutureKt;
|
||||
import net.mamoe.mirai.console.plugin.jvm.JavaPlugin;
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI;
|
||||
import net.mamoe.mirai.message.data.Message;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@ -152,6 +153,7 @@ public final class JCommandManager {
|
||||
* @return 执行结果
|
||||
* @see #executeCommandDetailedAsync(CoroutineScope, CommandSender, Object...)
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@NotNull
|
||||
public static CommandExecuteResult executeCommandDetailed(final @NotNull CommandSender sender, final @NotNull Object... args) throws InterruptedException {
|
||||
Objects.requireNonNull(sender, "sender");
|
||||
@ -171,6 +173,7 @@ public final class JCommandManager {
|
||||
* @return 执行结果
|
||||
* @see #executeCommandDetailed(CommandSender, Object...)
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
@NotNull
|
||||
public static CompletableFuture<@NotNull CommandExecuteResult>
|
||||
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 net.mamoe.mirai.console.command.internal.*
|
||||
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.MessageChain
|
||||
|
||||
@ -229,6 +230,7 @@ public suspend fun Command.execute(sender: CommandSender, vararg args: Any, chec
|
||||
*
|
||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): CommandExecuteResult {
|
||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||
return executeCommandDetailedInternal(messages, messages[0].toString().substringBefore(' '))
|
||||
@ -243,6 +245,7 @@ public suspend fun CommandSender.executeCommandDetailed(vararg messages: Any): C
|
||||
*
|
||||
* @see JCommandManager.executeCommandDetailed Java 方法
|
||||
*/
|
||||
@ConsoleExperimentalAPI
|
||||
public suspend fun CommandSender.executeCommandDetailed(messages: MessageChain): CommandExecuteResult {
|
||||
if (messages.isEmpty()) return CommandExecuteResult.CommandNotFound("")
|
||||
return executeCommandDetailedInternal(messages, messages[0].toString())
|
||||
|
@ -63,7 +63,7 @@ internal abstract class AbstractReflectionCommand @JvmOverloads constructor(
|
||||
DefaultSubCommandDescriptor(
|
||||
"",
|
||||
permission,
|
||||
onCommand = block2 { sender: CommandSender, args: Array<out Any> ->
|
||||
onCommand = { sender: CommandSender, args: Array<out Any> ->
|
||||
sender.onDefault(args)
|
||||
}
|
||||
)
|
||||
@ -292,7 +292,7 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
||||
params,
|
||||
subDescription,
|
||||
overridePermission?.value?.getInstance() ?: permission,
|
||||
onCommand = block { sender: CommandSender, args: Array<out Any> ->
|
||||
onCommand = { sender: CommandSender, args: Array<out Any> ->
|
||||
val result = if (notStatic) {
|
||||
if (hasSenderParam) {
|
||||
function.isSuspend
|
||||
@ -311,13 +311,4 @@ internal fun AbstractReflectionCommand.createSubCommand(
|
||||
context = context,
|
||||
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
|
||||
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.cio.CIO
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.util.KtorExperimentalAPI
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.engine.cio.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.util.*
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.UnstableDefault
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonConfiguration
|
||||
import net.mamoe.mirai.console.utils.ConsoleExperimentalAPI
|
||||
import net.mamoe.mirai.console.utils.retryCatching
|
||||
import java.io.File
|
||||
|
||||
@OptIn(UnstableDefault::class)
|
||||
internal val json = runCatching {
|
||||
Json(JsonConfiguration(isLenient = true, ignoreUnknownKeys = true))
|
||||
}.getOrElse { Json(JsonConfiguration.Stable) }
|
||||
internal val json = Json {
|
||||
isLenient = true
|
||||
ignoreUnknownKeys = true
|
||||
}
|
||||
|
||||
@OptIn(KtorExperimentalAPI::class)
|
||||
internal val Http = HttpClient(CIO)
|
||||
@ -64,7 +62,7 @@ internal object CuiPluginCenter : PluginCenter {
|
||||
}.getOrElse { 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() {
|
||||
@ -75,7 +73,7 @@ internal object CuiPluginCenter : PluginCenter {
|
||||
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" }
|
||||
plugins = result.result
|
||||
|
@ -69,25 +69,25 @@ public interface SerializerAwareValue<T> : Value<T> {
|
||||
@JvmStatic
|
||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||
public fun <T> SerializerAwareValue<T>.serialize(format: StringFormat): String {
|
||||
return format.stringify(this.serializer, Unit)
|
||||
return format.encodeToString(this.serializer, Unit)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||
public fun <T> SerializerAwareValue<T>.serialize(format: BinaryFormat): ByteArray {
|
||||
return format.dump(this.serializer, Unit)
|
||||
return format.encodeToByteArray(this.serializer, Unit)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||
public fun <T> SerializerAwareValue<T>.deserialize(format: StringFormat, value: String) {
|
||||
format.parse(this.serializer, value)
|
||||
format.decodeFromString(this.serializer, value)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
@ConsoleExperimentalAPI("will be changed due to reconstruction of kotlinx.serialization")
|
||||
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
|
||||
*/
|
||||
|
||||
@file:Suppress("NOTHING_TO_INLINE")
|
||||
@file:Suppress("NOTHING_TO_INLINE", "INVISIBLE_REFERENCE", "INVISIBLE_MEMBER")
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.builtins.*
|
||||
import kotlinx.serialization.KSerializer
|
||||
import net.mamoe.mirai.console.setting.SerializableValue.Companion.serializableValueWith
|
||||
import net.mamoe.mirai.console.setting.SerializerAwareValue
|
||||
import net.mamoe.mirai.console.setting.Setting
|
||||
import net.mamoe.mirai.console.setting.valueFromKType
|
||||
import net.mamoe.yamlkt.YamlDynamicSerializer
|
||||
import net.mamoe.yamlkt.YamlNullableDynamicSerializer
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.createInstance as createInstanceKotlin
|
||||
@ -142,63 +139,3 @@ internal fun KClass<*>.isPrimitiveOrBuiltInSerializableValue(): Boolean {
|
||||
@PublishedApi
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
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
|
||||
|
||||
import kotlinx.serialization.*
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialName
|
||||
import kotlinx.serialization.builtins.MapSerializer
|
||||
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.Setting
|
||||
import net.mamoe.mirai.console.setting.Value
|
||||
@ -53,7 +58,7 @@ internal abstract class SettingImpl {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun deserialize(decoder: Decoder) {
|
||||
val descriptor = descriptor
|
||||
with(decoder.beginStructure(descriptor, *settingUpdaterSerializerTypeArguments)) {
|
||||
with(decoder.beginStructure(descriptor)) {
|
||||
if (decodeSequentially()) {
|
||||
var index = 0
|
||||
repeat(decodeCollectionSize(descriptor)) {
|
||||
@ -70,7 +75,7 @@ internal abstract class SettingImpl {
|
||||
var serialName: String? = null
|
||||
innerLoop@ while (true) {
|
||||
val index = decodeElementIndex(descriptor)
|
||||
if (index == CompositeDecoder.READ_DONE) {
|
||||
if (index == CompositeDecoder.DECODE_DONE) {
|
||||
check(serialName == null) { "name must be null at this moment." }
|
||||
break@outerLoop
|
||||
}
|
||||
@ -102,7 +107,7 @@ internal abstract class SettingImpl {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun serialize(encoder: Encoder, value: Unit) {
|
||||
val descriptor = descriptor
|
||||
with(encoder.beginCollection(descriptor, valueNodes.size, *settingUpdaterSerializerTypeArguments)) {
|
||||
with(encoder.beginCollection(descriptor, valueNodes.size)) {
|
||||
var index = 0
|
||||
|
||||
// val vSerializer = settingUpdaterSerializerTypeArguments[1] as KSerializer<Any?>
|
||||
|
@ -9,11 +9,11 @@
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
|
||||
import kotlinx.serialization.Decoder
|
||||
import kotlinx.serialization.Encoder
|
||||
import kotlinx.serialization.KSerializer
|
||||
import kotlinx.serialization.SerialDescriptor
|
||||
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.*
|
||||
|
||||
/**
|
||||
@ -98,6 +98,7 @@ internal abstract class ShortValueImpl : ShortValue, SerializerAwareValue<Short>
|
||||
else value.hashCode() * 31
|
||||
}
|
||||
}
|
||||
|
||||
internal abstract class IntValueImpl : IntValue, SerializerAwareValue<Int>, KSerializer<Unit>, AbstractValueImpl<Int> {
|
||||
constructor()
|
||||
constructor(default: Int) {
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.setting.internal
|
||||
|
||||
import kotlinx.serialization.ImplicitReflectionSerializer
|
||||
import kotlinx.serialization.UnsafeSerializationApi
|
||||
import kotlinx.serialization.serializer
|
||||
import net.mamoe.yamlkt.Yaml
|
||||
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 {
|
||||
kotlin.runCatching {
|
||||
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
|
||||
|
||||
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.full.findAnnotation
|
||||
|
||||
|
@ -9,9 +9,7 @@
|
||||
|
||||
package net.mamoe.mirai.console.setting
|
||||
|
||||
import kotlinx.serialization.UnstableDefault
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonConfiguration
|
||||
import net.mamoe.mirai.console.utils.ConsoleInternalAPI
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -34,20 +32,19 @@ internal class SettingTest {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(UnstableDefault::class)
|
||||
private val jsonPrettyPrint = Json(JsonConfiguration(prettyPrint = true))
|
||||
private val json = Json(JsonConfiguration.Stable)
|
||||
private val jsonPrettyPrint = Json { prettyPrint = true }
|
||||
private val json = Json {}
|
||||
|
||||
@Test
|
||||
fun testStringify() {
|
||||
val setting = MySetting()
|
||||
|
||||
var string = json.stringify(setting.updaterSerializer, Unit)
|
||||
var string = json.encodeToString(setting.updaterSerializer, Unit)
|
||||
assertEquals("""{"int":1,"map":{},"map2":{}}""", string)
|
||||
|
||||
setting.int = 2
|
||||
|
||||
string = json.stringify(setting.updaterSerializer, Unit)
|
||||
string = json.encodeToString(setting.updaterSerializer, Unit)
|
||||
assertEquals("""{"int":2,"map":{},"map2":{}}""", string)
|
||||
}
|
||||
|
||||
@ -57,10 +54,10 @@ internal class SettingTest {
|
||||
|
||||
assertEquals(1, setting.int)
|
||||
|
||||
json.parse(
|
||||
json.decodeFromString(
|
||||
setting.updaterSerializer, """
|
||||
{"int":3,"map":{},"map2":{}}
|
||||
""".trimIndent()
|
||||
{"int":3,"map":{},"map2":{}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(3, setting.int)
|
||||
@ -77,10 +74,10 @@ internal class SettingTest {
|
||||
|
||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||
|
||||
json.parse(
|
||||
json.decodeFromString(
|
||||
setting.updaterSerializer, """
|
||||
{"int":1,"map":{"t":"test"},"map2":{}}
|
||||
""".trimIndent()
|
||||
{"int":1,"map":{"t":"test"},"map2":{}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(mapOf("t" to "test").toString(), delegation().toString())
|
||||
@ -100,10 +97,10 @@ internal class SettingTest {
|
||||
|
||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||
|
||||
json.parse(
|
||||
json.decodeFromString(
|
||||
setting.updaterSerializer, """
|
||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||
""".trimIndent()
|
||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(mapOf("t" to mapOf("f" to "test")).toString(), delegation().toString())
|
||||
@ -125,10 +122,10 @@ internal class SettingTest {
|
||||
|
||||
assertEquals(mutableMapOf(), delegation()) // delegation
|
||||
|
||||
json.parse(
|
||||
json.decodeFromString(
|
||||
setting.updaterSerializer, """
|
||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||
""".trimIndent()
|
||||
{"int":1,"map":{},"map2":{"t":{"f":"test"}}}
|
||||
""".trimIndent()
|
||||
)
|
||||
|
||||
assertEquals(mapOf("f" to "test").toString(), delegation().toString())
|
||||
|
@ -2,6 +2,7 @@
|
||||
plugins {
|
||||
id("com.jfrog.bintray") version Versions.bintray apply false
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile::class.java) {
|
||||
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 {
|
||||
repositories {
|
||||
mavenLocal()
|
||||
gradlePluginPortal()
|
||||
jcenter()
|
||||
maven(url = "https://dl.bintray.com/kotlin/kotlin-eap")
|
||||
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"
|
||||
|
Loading…
Reference in New Issue
Block a user