From 2f903cef9e884873b9c9201c0b253283bc403406 Mon Sep 17 00:00:00 2001 From: Karlatemp Date: Sat, 26 Dec 2020 15:55:13 +0800 Subject: [PATCH 1/2] Mirai code (#768) * Mirai Code * cleanup code * mirai code of MarketFace --- .../kotlin/message/code/CodableMessage.kt | 7 +- .../kotlin/message/code/MiraiCode.kt | 12 +- .../kotlin/message/code/internal/impl.kt | 154 +++++++++++------- .../src/commonMain/kotlin/message/data/At.kt | 4 + .../commonMain/kotlin/message/data/AtAll.kt | 8 + .../commonMain/kotlin/message/data/Face.kt | 4 + .../kotlin/message/data/HummerMessage.kt | 15 ++ .../commonMain/kotlin/message/data/Image.kt | 3 + .../kotlin/message/data/MessageChain.kt | 10 +- .../kotlin/message/data/PlainText.kt | 8 +- .../kotlin/message/data/RichMessage.kt | 15 +- .../kotlin/message/code/TestMiraiCode.kt | 46 ++++++ .../src/commonMain/kotlin/message/faceImpl.kt | 8 + .../commonMain/kotlin/message/imagesImpl.kt | 4 + 14 files changed, 237 insertions(+), 61 deletions(-) create mode 100644 mirai-core-api/src/commonTest/kotlin/message/code/TestMiraiCode.kt diff --git a/mirai-core-api/src/commonMain/kotlin/message/code/CodableMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/code/CodableMessage.kt index 3353f824e..60e0ab94f 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/code/CodableMessage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/code/CodableMessage.kt @@ -10,6 +10,7 @@ package net.mamoe.mirai.message.code import net.mamoe.mirai.message.data.* +import net.mamoe.mirai.utils.MiraiExperimentalApi /** @@ -36,5 +37,9 @@ public interface CodableMessage : Message { * * @suppress 警告: 此 API 可能在任何时刻被改变 */ - public fun toMiraiCode(): String = this.toString() + public fun toMiraiCode(): String = buildString { appendMiraiCode(this) } + + // Using StringBuilder faster than direct plus objects + @MiraiExperimentalApi + public fun appendMiraiCode(builder: StringBuilder) } \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/message/code/MiraiCode.kt b/mirai-core-api/src/commonMain/kotlin/message/code/MiraiCode.kt index b97e7ceee..cd073c210 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/code/MiraiCode.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/code/MiraiCode.kt @@ -12,11 +12,21 @@ package net.mamoe.mirai.message.code +import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.message.code.internal.parseMiraiCodeImpl import net.mamoe.mirai.message.data.Message import net.mamoe.mirai.message.data.MessageChain +import net.mamoe.mirai.utils.safeCast /** * 解析形如 "[mirai:]" 的 mirai 码, 即 [Message.toString] 返回的内容. */ -public fun String.parseMiraiCode(): MessageChain = parseMiraiCodeImpl() \ No newline at end of file +@JvmOverloads +public fun String.parseMiraiCode(contact: Contact? = null): MessageChain = parseMiraiCodeImpl(contact) + +public fun Iterable.toMiraiCode(): String = iterator().toMiraiCode() +public fun Iterator.toMiraiCode(): String = buildString { + this@toMiraiCode.forEach { + it.safeCast()?.appendMiraiCode(this) + } +} diff --git a/mirai-core-api/src/commonMain/kotlin/message/code/internal/impl.kt b/mirai-core-api/src/commonMain/kotlin/message/code/internal/impl.kt index 23ac5721c..d85efa46c 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/code/internal/impl.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/code/internal/impl.kt @@ -11,55 +11,95 @@ package net.mamoe.mirai.message.code.internal +import net.mamoe.mirai.contact.Contact import net.mamoe.mirai.message.data.* +import net.mamoe.mirai.utils.MiraiInternalApi -@Suppress("RegExpRedundantEscape") // required on android -internal val codeRegex = Regex("""(?:\[mirai:([^\]]*)?:(.*?)?\])|(?:\[mirai:([^:]+)\])""") - -internal fun String.parseMiraiCodeImpl(): MessageChain = buildMessageChain { +internal fun String.parseMiraiCodeImpl(contact: Contact?): MessageChain = buildMessageChain { forEachMiraiCode { origin, name, args -> if (name == null) { - add(PlainText(origin)) + add(PlainText(origin.decodeMiraiCode())) return@forEachMiraiCode } val parser = MiraiCodeParsers[name] ?: kotlin.run { - add(PlainText(origin)) + add(PlainText(origin.decodeMiraiCode())) return@forEachMiraiCode } parser.argsRegex.matchEntire(args) ?.destructured ?.let { parser.runCatching { - mapper(it) + contact.mapper(it) }.getOrNull() } ?.let(::add) - ?: add(PlainText(origin)) + ?: add(PlainText(origin.decodeMiraiCode())) } } -internal inline fun String.forEachMiraiCode(crossinline block: (origin: String, name: String?, args: String) -> Unit) { - var lastIndex = 0 - for (result in codeRegex.findAll(this)) { - if (result.range.first != lastIndex) { - // skipped string - block(substring(lastIndex, result.range.first), null, "") +internal fun String.forEachMiraiCode(block: (origin: String, name: String?, args: String) -> Unit) { + var pos = 0 + var lastPos = 0 + val len = length - 7 // [mirai: + fun findEnding(start: Int): Int { + var pos0 = start + while (pos0 < length) { + when (get(pos0)) { + '\\' -> pos0 += 2 + ']' -> return pos0 + else -> pos0++ + } } - - lastIndex = result.range.last + 1 - if (result.groups[3] != null) { - // no param - block(result.value, result.groups[3]!!.value, "") - } else block(result.value, result.groups[1]!!.value, result.groups[2]?.value ?: "") + return -1 } - if (lastIndex != this.length) { - block(substring(lastIndex, this.length), null, "") + while (pos < len) { + when (get(pos)) { + '\\' -> { + pos += 2 + } + '[' -> { + if (get(pos + 1) == 'm' && get(pos + 2) == 'i' && + get(pos + 3) == 'r' && get(pos + 4) == 'a' && + get(pos + 5) == 'i' && get(pos + 6) == ':' + ) { + val begin = pos + pos += 7 + val ending = findEnding(pos) + if (ending == -1) { + block(substring(lastPos), null, "") + return + } else { + if (lastPos < begin) { + block(substring(lastPos, begin), null, "") + } + val v = substring(begin, ending + 1) + val splitter = v.indexOf(':', 7) + block( + v, if (splitter == -1) + v.substring(7, v.length - 1) + else v.substring(7, splitter), + if (splitter == -1) { + "" + } else v.substring(splitter + 1, v.length - 1) + ) + lastPos = ending + 1 + pos = lastPos + } + } else pos++ + } + else -> { + pos++ + } + } + } + if (lastPos < length) { + block(substring(lastPos), null, "") } } internal object MiraiCodeParsers : Map by mapOf( - "at" to MiraiCodeParser(Regex("""(\d*)""")) { (target, _) -> + "at" to MiraiCodeParser(Regex("""(\d*)""")) { (target) -> At(target.toLong()) }, "atall" to MiraiCodeParser(Regex("")) { @@ -79,40 +119,44 @@ internal object MiraiCodeParsers : Map by mapOf( }, "flash" to MiraiCodeParser(Regex("""(.*)""")) { (id) -> Image(id).flash() + }, + "service" to MiraiCodeParser(Regex("""(\d*),(.*)""")) { (id, content) -> + SimpleServiceMessage(id.toInt(), content.decodeMiraiCode()) + }, + "app" to MiraiCodeParser(Regex("""(.*)""")) { (content) -> + LightApp(content.decodeMiraiCode()) } ) -/* -internal object MiraiCodeParsers2 : Map Message?> by mapOf( - "at" to l@{ args -> - val group = args.split(',') - if (group.size != 2) return@l null - val target = group[0].toLongOrNull() ?: return@l null - @Suppress("INVISIBLE_MEMBER") - At(target, group[1]) - }, - "atall" to l@{ - AtAll - }, - "poke" to l@{ args -> - val group = args.split(',') - if (group.size != 2) return@l null - val type = group[1].toIntOrNull() ?: return@l null - val id = group[2].toIntOrNull() ?: return@l null - @Suppress("INVISIBLE_MEMBER") - PokeMessage(group[0], type, id) - }, - "vipface" to l@{ args -> - val group = args.split(',') - if (group.size != 2) return@l null - val type = group[1].toIntOrNull() ?: return@l null - val id = group[2].toIntOrNull() ?: return@l null - @Suppress("INVISIBLE_MEMBER") - PokeMessage(group[0], type, id) - } -)*/ - internal class MiraiCodeParser( val argsRegex: Regex, - val mapper: MiraiCodeParser.(MatchResult.Destructured) -> Message? -) \ No newline at end of file + val mapper: Contact?.(MatchResult.Destructured) -> Message? +) + +@MiraiInternalApi +public fun StringBuilder.appendAsMiraiCode(value: String): StringBuilder = apply { + value.forEach { char -> + when (char) { + '[', ']', + ':', ',', + '\\', + -> append("\\").append(char) + '\n' -> append("\\n") + '\r' -> append("\\r") + else -> append(char) + } + } +} + +@Suppress("RegExpRedundantEscape") +internal val DECODE_MIRAI_CODE_REGEX = """\\.""".toRegex() +internal val DECODE_MIRAI_CODE_TRANSLATOR: (MatchResult) -> String = { + when (it.value[1]) { + 'n' -> "\n" + 'r' -> "\r" + '\n' -> "" + else -> it.value.substring(1) + } +} + +internal fun String.decodeMiraiCode() = replace(DECODE_MIRAI_CODE_REGEX, DECODE_MIRAI_CODE_TRANSLATOR) diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/At.kt b/mirai-core-api/src/commonMain/kotlin/message/data/At.kt index b44bb75dd..627e5b84e 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/At.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/At.kt @@ -55,6 +55,10 @@ public data class At( return "@${member.nameCardOrNick}" } + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:at:").append(target).append(']') + } + public companion object { /** * 构造一个 [At], 仅供内部使用, 否则可能造成消息无法发出的问题. diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/AtAll.kt b/mirai-core-api/src/commonMain/kotlin/message/data/AtAll.kt index ed2e94d26..98a205e5f 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/AtAll.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/AtAll.kt @@ -40,6 +40,14 @@ public object AtAll : return other === this } + override fun toMiraiCode(): String { + return toString() + } + + override fun appendMiraiCode(builder: StringBuilder) { + builder.append(toString()) + } + public override fun hashCode(): Int { return display.hashCode() } diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Face.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Face.kt index 46724f811..b81ab0ed6 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Face.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/Face.kt @@ -29,6 +29,10 @@ public data class Face(public val id: Int) : // used in delegation public val name: String get() = contentToString().let { it.substring(1, it.length - 1) } public override fun contentToString(): String = names.getOrElse(id) { "[表情]" } + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:face:").append(id).append(']') + } + public override fun equals(other: Any?): Boolean = other is Face && other.id == this.id public override fun hashCode(): Int = id diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt index ab372b67c..53b97cf25 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/HummerMessage.kt @@ -16,6 +16,7 @@ package net.mamoe.mirai.message.data import kotlinx.serialization.Contextual import kotlinx.serialization.Serializable import net.mamoe.mirai.message.code.CodableMessage +import net.mamoe.mirai.message.code.internal.appendAsMiraiCode import net.mamoe.mirai.message.data.VipFace.Kind import net.mamoe.mirai.utils.MiraiInternalApi import net.mamoe.mirai.utils.PlannedRemoval @@ -173,6 +174,12 @@ public data class PokeMessage @MiraiInternalApi constructor( private val stringValue = "[mirai:poke:$name,$pokeType,$id]" + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:poke:").appendAsMiraiCode(name) + .append(',').append(pokeType).append(',').append(id) + .append(']') + } + override fun toString(): String = stringValue override fun contentToString(): String = "[戳一戳]" //businessType=0x00000001(1) @@ -290,6 +297,9 @@ public data class VipFace @MiraiInternalApi constructor( private infix fun Int.to(name: String): Kind = Kind(this, name) } + override fun appendMiraiCode(builder: StringBuilder) { + builder.append(stringValue) // TODO: + } private val stringValue = "[mirai:vipface:$kind,$count]" @@ -339,6 +349,11 @@ public data class FlashImage( private val stringValue: String by lazy(LazyThreadSafetyMode.NONE) { "[mirai:flash:${image.imageId}]" } + override fun appendMiraiCode(builder: StringBuilder) { + builder.append(stringValue) + } + + override fun toMiraiCode(): String = stringValue public override fun toString(): String = stringValue public override fun contentToString(): String = "[闪照]" } diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt index 66b0dcfac..e4b03a0cc 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/Image.kt @@ -229,6 +229,9 @@ public sealed class AbstractImage : Image { final override fun toString(): String = _stringValue!! final override fun contentToString(): String = "[图片]" + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:image:").append(imageId).append("]") + } } diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt index 914c8155f..6a4dff71e 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/MessageChain.kt @@ -20,8 +20,10 @@ import kotlinx.serialization.descriptors.SerialDescriptor import kotlinx.serialization.encoding.Decoder import kotlinx.serialization.encoding.Encoder import net.mamoe.mirai.event.events.MessageEvent +import net.mamoe.mirai.message.code.CodableMessage import net.mamoe.mirai.message.data.MessageSource.Key.quote import net.mamoe.mirai.message.data.MessageSource.Key.recall +import net.mamoe.mirai.utils.safeCast import kotlin.js.JsName import kotlin.reflect.KProperty @@ -56,7 +58,7 @@ import kotlin.reflect.KProperty */ @Serializable(MessageChain.Serializer::class) @Suppress("FunctionName", "DeprecatedCallableAddReplaceWith", "INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") -public interface MessageChain : Message, List, RandomAccess { +public interface MessageChain : Message, List, RandomAccess, CodableMessage { /** * 元素数量. [EmptyMessageChain] 不参加计数. */ @@ -98,6 +100,10 @@ public interface MessageChain : Message, List, RandomAccess { override fun deserialize(decoder: Decoder): MessageChain = delegate.deserialize(decoder).asMessageChain() override fun serialize(encoder: Encoder, value: MessageChain): Unit = delegate.serialize(encoder, value) } + + override fun appendMiraiCode(builder: StringBuilder) { + forEach { it.safeCast()?.appendMiraiCode(builder) } + } } // region accessors @@ -430,4 +436,6 @@ public object EmptyMessageChain : MessageChain, Iterator, List = this public override fun hasNext(): Boolean = false public override fun next(): SingleMessage = throw NoSuchElementException("EmptyMessageChain is empty.") + override fun toMiraiCode(): String = "" + override fun appendMiraiCode(builder: StringBuilder) {} } \ No newline at end of file diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/PlainText.kt b/mirai-core-api/src/commonMain/kotlin/message/data/PlainText.kt index 8bdf8f050..9ad4dc962 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/PlainText.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/PlainText.kt @@ -14,6 +14,8 @@ package net.mamoe.mirai.message.data import kotlinx.serialization.Serializable +import net.mamoe.mirai.message.code.CodableMessage +import net.mamoe.mirai.message.code.internal.appendAsMiraiCode /** * 纯文本. 可含 emoji 表情如 😊. @@ -23,13 +25,17 @@ import kotlinx.serialization.Serializable @Serializable public data class PlainText( public val content: String -) : MessageContent { +) : MessageContent, CodableMessage { @Suppress("unused") public constructor(charSequence: CharSequence) : this(charSequence.toString()) public override fun toString(): String = content public override fun contentToString(): String = content + override fun appendMiraiCode(builder: StringBuilder) { + builder.appendAsMiraiCode(content) + } + public companion object } diff --git a/mirai-core-api/src/commonMain/kotlin/message/data/RichMessage.kt b/mirai-core-api/src/commonMain/kotlin/message/data/RichMessage.kt index 34c1db42f..cfe819564 100644 --- a/mirai-core-api/src/commonMain/kotlin/message/data/RichMessage.kt +++ b/mirai-core-api/src/commonMain/kotlin/message/data/RichMessage.kt @@ -14,6 +14,8 @@ package net.mamoe.mirai.message.data import kotlinx.serialization.Serializable +import net.mamoe.mirai.message.code.CodableMessage +import net.mamoe.mirai.message.code.internal.appendAsMiraiCode import net.mamoe.mirai.utils.MiraiExperimentalApi import net.mamoe.mirai.utils.PlannedRemoval import net.mamoe.mirai.utils.safeCast @@ -94,10 +96,14 @@ public interface RichMessage : MessageContent, ConstrainSingle { * @see ServiceMessage 服务消息 */ @Serializable -public data class LightApp(override val content: String) : RichMessage { +public data class LightApp(override val content: String) : RichMessage, CodableMessage { public companion object Key : AbstractMessageKey({ it.safeCast() }) public override fun toString(): String = "[mirai:app:$content]" + + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:app:").appendAsMiraiCode(content).append(']') + } } /** @@ -130,6 +136,7 @@ public class SimpleServiceMessage( result = 31 * result + content.hashCode() return result } + } @@ -141,7 +148,7 @@ public class SimpleServiceMessage( * @see LightApp 小程序类型消息 * @see SimpleServiceMessage */ -public interface ServiceMessage : RichMessage { +public interface ServiceMessage : RichMessage, CodableMessage { public companion object Key : AbstractPolymorphicMessageKey(RichMessage, { it.safeCast() }) @@ -149,6 +156,10 @@ public interface ServiceMessage : RichMessage { * 目前未知, XML 一般为 60, JSON 一般为 1 */ public val serviceId: Int + + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:service:").append(serviceId).append(',').appendAsMiraiCode(content).append(']') + } } @Suppress("FunctionName") diff --git a/mirai-core-api/src/commonTest/kotlin/message/code/TestMiraiCode.kt b/mirai-core-api/src/commonTest/kotlin/message/code/TestMiraiCode.kt new file mode 100644 index 000000000..a82475db6 --- /dev/null +++ b/mirai-core-api/src/commonTest/kotlin/message/code/TestMiraiCode.kt @@ -0,0 +1,46 @@ +/* + * Copyright 2019-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.message.code + +import net.mamoe.mirai.message.data.* +import org.junit.jupiter.api.Test +import kotlin.test.assertEquals + +class TestMiraiCode { + @Test + fun testCodes() { + assertEquals(AtAll.asMessageChain(), "[mirai:atall]".parseMiraiCode()) + assertEquals(PlainText("[Hello").asMessageChain(), "\\[Hello".parseMiraiCode()) + assertEquals(buildMessageChain { + +PlainText("1") + +AtAll + +PlainText("2345") + +AtAll + }, "1[mirai:atall]2345[mirai:atall]".parseMiraiCode()) + assertEquals(buildMessageChain { + +PlainText("1") + +AtAll + +PlainText("2345[mirai:atall") + }, "1[mirai:atall]2345[mirai:atall".parseMiraiCode()) + assertEquals(buildMessageChain { + +PlainText("[mirai:atall]") + }, "\\[mirai:atall]".parseMiraiCode()) + assertEquals(buildMessageChain { + +PlainText("[mirai:atall]") + }, "[mirai:atall\\]".parseMiraiCode()) + assertEquals(buildMessageChain { + +PlainText("[mirai:atall]") + }, "[mirai\\:atall]".parseMiraiCode()) + assertEquals(buildMessageChain { + +SimpleServiceMessage(1, "[HiHi!!!\\]") + +PlainText(" XE") + }, "[mirai:service:1,\\[HiHi!!!\\\\\\]] XE".parseMiraiCode()) + } +} \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/message/faceImpl.kt b/mirai-core/src/commonMain/kotlin/message/faceImpl.kt index c5e85b646..e4976800d 100644 --- a/mirai-core/src/commonMain/kotlin/message/faceImpl.kt +++ b/mirai-core/src/commonMain/kotlin/message/faceImpl.kt @@ -17,8 +17,10 @@ import net.mamoe.mirai.internal.network.protocol.data.proto.ImMsgBody import net.mamoe.mirai.internal.utils.hexToBytes import net.mamoe.mirai.internal.utils.io.serialization.toByteArray import net.mamoe.mirai.internal.utils.toByteArray +import net.mamoe.mirai.message.code.internal.appendAsMiraiCode import net.mamoe.mirai.message.data.Face import net.mamoe.mirai.message.data.MarketFace +import net.mamoe.mirai.utils.MiraiExperimentalApi internal val FACE_BUF = "00 01 00 04 52 CC F5 D0".hexToBytes() @@ -51,5 +53,11 @@ internal data class MarketFaceImpl internal constructor( override val name: String = delegate.faceName.decodeToString() @Transient override val id: Int = delegate.tabId + + @MiraiExperimentalApi + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:marketface:").append(id).append(",").appendAsMiraiCode(name).append(']') + } + override fun toString() = "[mirai:marketface:$id,$name]" } \ No newline at end of file diff --git a/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt b/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt index 8d18a6544..bd1c34530 100644 --- a/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt +++ b/mirai-core/src/commonMain/kotlin/message/imagesImpl.kt @@ -121,6 +121,10 @@ internal abstract class AbstractImage : Image { // make sealed in 1.3.0 ? final override fun toString(): String = _stringValue!! final override fun contentToString(): String = "[图片]" + + override fun appendMiraiCode(builder: StringBuilder) { + builder.append("[mirai:image:").append(imageId).append("]") + } } internal interface ConstOriginUrlAware : Image { From 471e70205e36a05572d0a2c85dcb66eeb955aaa2 Mon Sep 17 00:00:00 2001 From: Karlatemp Date: Sat, 26 Dec 2020 16:43:10 +0800 Subject: [PATCH 2/2] Covert SimpleListenerHostTest to kotlin --- .../event/SimpleListenerHostTestJava.kt | 42 +++++++++++++++++++ .../javatest/SimpleListenerHostTest.java | 41 ------------------ 2 files changed, 42 insertions(+), 41 deletions(-) create mode 100644 mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt delete mode 100644 mirai-core/src/jvmTest/java/net/mamoe/mirai/javatest/SimpleListenerHostTest.java diff --git a/mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt b/mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt new file mode 100644 index 000000000..3ed7be402 --- /dev/null +++ b/mirai-core-api/src/jvmTest/kotlin/event/SimpleListenerHostTestJava.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2019-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.event + +import kotlinx.coroutines.CoroutineScope +import net.mamoe.mirai.JavaFriendlyAPI +import net.mamoe.mirai.utils.EventListenerLikeJava +import org.junit.jupiter.api.Test +import java.util.concurrent.atomic.AtomicBoolean +import kotlin.coroutines.EmptyCoroutineContext + +@JavaFriendlyAPI +@EventListenerLikeJava +class SimpleListenerHostTestJava { + @Test + fun testJavaSimpleListenerHostWork() { + val called = AtomicBoolean() + val host: SimpleListenerHost = object : SimpleListenerHost() { + @EventHandler + @EventListenerLikeJava + fun testListen( + event: AbstractEvent? + ) { + println(event) + called.set(true) + } + } + val scope = CoroutineScope(EmptyCoroutineContext) + scope.registerEvents(host) + object : AbstractEvent() {}.__broadcastJava() + if (!called.get()) { + throw AssertionError("JavaTest: SimpleListenerHost Failed.") + } + } +} \ No newline at end of file diff --git a/mirai-core/src/jvmTest/java/net/mamoe/mirai/javatest/SimpleListenerHostTest.java b/mirai-core/src/jvmTest/java/net/mamoe/mirai/javatest/SimpleListenerHostTest.java deleted file mode 100644 index 6d32a221c..000000000 --- a/mirai-core/src/jvmTest/java/net/mamoe/mirai/javatest/SimpleListenerHostTest.java +++ /dev/null @@ -1,41 +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 AGPLv3 license that can be found through the following link. - * - * https://github.com/mamoe/mirai/blob/master/LICENSE - */ - -package net.mamoe.mirai.javatest; - -import kotlin.coroutines.EmptyCoroutineContext; -import kotlinx.coroutines.CoroutineScope; -import kotlinx.coroutines.CoroutineScopeKt; -import net.mamoe.mirai.event.*; -import org.junit.jupiter.api.Test; - -import java.util.concurrent.atomic.AtomicBoolean; - -public class SimpleListenerHostTest { - @Test - public void testJavaSimpleListenerHostWork() { - AtomicBoolean called = new AtomicBoolean(); - final SimpleListenerHost host = new SimpleListenerHost() { - @EventHandler - public void testListen( - AbstractEvent event - ) { - System.out.println(event); - called.set(true); - } - }; - CoroutineScope scope = CoroutineScopeKt.CoroutineScope(EmptyCoroutineContext.INSTANCE); - Events.registerEvents(scope, host); - EventKt.broadcast(new AbstractEvent() { - }); - if (!called.get()) { - throw new AssertionError("JavaTest: SimpleListenerHost Failed."); - } - } -}