forked from mamoe/mirai
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
291 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
@file:Suppress("UNUSED_VARIABLE") | ||
|
||
plugins { | ||
kotlin("multiplatform") | ||
id("kotlinx-atomicfu") | ||
kotlin("plugin.serialization") | ||
id("signing") | ||
`maven-publish` | ||
id("com.jfrog.bintray") version Versions.Publishing.bintray | ||
} | ||
|
||
description = "Mirai serialization module" | ||
|
||
val isAndroidSDKAvailable: Boolean by project | ||
|
||
kotlin { | ||
if (isAndroidSDKAvailable) { | ||
apply(from = rootProject.file("gradle/android.gradle")) | ||
android("android") { | ||
publishAllLibraryVariants() | ||
} | ||
} else { | ||
println( | ||
"""Android SDK 可能未安装. | ||
$name 的 Android 目标编译将不会进行. | ||
这不会影响 Android 以外的平台的编译. | ||
""".trimIndent() | ||
) | ||
println( | ||
"""Android SDK might not be installed. | ||
Android target of $name will not be compiled. | ||
It does no influence on the compilation of other platforms. | ||
""".trimIndent() | ||
) | ||
} | ||
|
||
jvm() | ||
|
||
sourceSets { | ||
all { | ||
languageSettings.enableLanguageFeature("InlineClasses") | ||
languageSettings.useExperimentalAnnotation("kotlin.Experimental") | ||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiInternalAPI") | ||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.utils.MiraiExperimentalAPI") | ||
languageSettings.useExperimentalAnnotation("net.mamoe.mirai.LowLevelAPI") | ||
languageSettings.useExperimentalAnnotation("kotlin.ExperimentalUnsignedTypes") | ||
languageSettings.useExperimentalAnnotation("kotlin.experimental.ExperimentalTypeInference") | ||
languageSettings.useExperimentalAnnotation("kotlin.time.ExperimentalTime") | ||
languageSettings.useExperimentalAnnotation("kotlin.contracts.ExperimentalContracts") | ||
languageSettings.progressiveMode = true | ||
} | ||
|
||
val commonMain by getting { | ||
dependencies { | ||
api(kotlin("stdlib")) | ||
api(project(":mirai-core")) | ||
} | ||
} | ||
val commonTest by getting { | ||
dependencies { | ||
api(kotlin("test-annotations-common")) | ||
api(kotlin("test-common")) | ||
} | ||
} | ||
|
||
if (isAndroidSDKAvailable) { | ||
val androidMain by getting { | ||
dependencies { | ||
} | ||
} | ||
|
||
val androidTest by getting { | ||
dependencies { | ||
} | ||
} | ||
} | ||
|
||
val jvmMain by getting { | ||
dependencies { | ||
runtimeOnly(files("build/classes/kotlin/jvm/main")) // classpath is not properly set by IDE | ||
} | ||
} | ||
|
||
val jvmTest by getting { | ||
dependencies { | ||
implementation(kotlin("test")) | ||
implementation(kotlin("test-junit")) | ||
|
||
runtimeOnly(files("build/classes/kotlin/jvm/test")) // classpath is not properly set by IDE | ||
} | ||
} | ||
} | ||
} | ||
|
||
apply(from = rootProject.file("gradle/publish.gradle")) |
123 changes: 123 additions & 0 deletions
123
mirai-serialization/src/commonMain/kotlin/net/mamoe/mirai/message/code/MiraiCode.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* | ||
* 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:JvmMultifileClass | ||
@file:JvmName("MiraiCode") | ||
@file:Suppress("INVISIBLE_MEMBER") | ||
|
||
package net.mamoe.mirai.message.code | ||
|
||
import net.mamoe.mirai.message.data.* | ||
import net.mamoe.mirai.utils.SinceMirai | ||
import kotlin.jvm.JvmMultifileClass | ||
import kotlin.jvm.JvmName | ||
|
||
@Suppress("RegExpRedundantEscape") // required on android | ||
internal val codeRegex = Regex("""(?:\[mirai:([^\]]*)?:(.*?)?\])|(?:\[mirai:(.*?)\])""") | ||
|
||
/** | ||
* 解析形如 "[mirai:]" 的 mirai 码, 即 [Message.toString] 返回的内容. | ||
*/ | ||
@SinceMirai("1.1.0") | ||
fun String.parseMiraiCode(): MessageChain = buildMessageChain { | ||
forEachMiraiCode { origin, name, args -> | ||
if (name == null) { | ||
add(origin.toMessage()) | ||
return@forEachMiraiCode | ||
} | ||
val parser = MiraiCodeParsers[name] ?: kotlin.run { | ||
add(origin.toMessage()) | ||
return@forEachMiraiCode | ||
} | ||
parser.argsRegex.matchEntire(args) | ||
?.destructured | ||
?.let { | ||
parser.runCatching { | ||
mapper(it) | ||
}.getOrNull() | ||
} | ||
?.let(::add) | ||
?: add(origin.toMessage()) | ||
} | ||
} | ||
|
||
private 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(result.value, null, substring(lastIndex, result.range.first)) | ||
} | ||
|
||
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 ?: "") | ||
} | ||
} | ||
|
||
internal object MiraiCodeParsers : Map<String, MiraiCodeParser> by mapOf( | ||
"at" to MiraiCodeParser(Regex("""(\d*),(.*)""")) { (target, display) -> | ||
At._lowLevelConstructAtInstance(target.toLong(), display) | ||
}, | ||
"atall" to MiraiCodeParser(Regex("")) { | ||
AtAll | ||
}, | ||
"poke" to MiraiCodeParser(Regex("(.*)?,(\\d*),(-?\\d*)")) { (name, type, id) -> | ||
PokeMessage(name, type.toInt(), id.toInt()) | ||
}, | ||
"vipface" to MiraiCodeParser(Regex("""\((\d*),(.*)\),(\d*)""")) { (id, name, count) -> | ||
VipFace(VipFace.Kind(id.toInt(), name), count.toInt()) | ||
}, | ||
"face" to MiraiCodeParser(Regex("""(\d*)""")) { (id) -> | ||
Face(id.toInt()) | ||
}, | ||
"image" to MiraiCodeParser(Regex("""(.*)""")) { (id) -> | ||
Image(id) | ||
}, | ||
"flash" to MiraiCodeParser(Regex("""(.*)""")) { (id) -> | ||
Image(id).flash() | ||
} | ||
) | ||
|
||
/* | ||
internal object MiraiCodeParsers2 : Map<String, (args: String) -> 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? | ||
) |
69 changes: 69 additions & 0 deletions
69
...i-serialization/src/commonTest/kotlin/net/mamoe/mirai/message/code/MiraiCodeParserTest.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
/* | ||
* 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("INVISIBLE_MEMBER", "INVISIBLE_REFERENCE") | ||
|
||
package net.mamoe.mirai.message.code | ||
|
||
import net.mamoe.mirai.message.data.* | ||
import net.mamoe.mirai.message.data.VipFace.Companion.AiXin | ||
import kotlin.test.Test | ||
import kotlin.test.assertEquals | ||
|
||
internal class MiraiCodeParserTest { | ||
|
||
@Test | ||
fun testSplit() { | ||
val str = "sadvass][ [mirai:at:1,test]]vdsavs [mirai:atall]" | ||
assertEquals(str, str.parseMiraiCode().toString()) | ||
} | ||
|
||
@Test | ||
fun at() { | ||
val str = "[mirai:at:1,test]" | ||
assertEquals(At._lowLevelConstructAtInstance(1, "test"), str.parseMiraiCode()[0]) | ||
|
||
fun testPlain(str: String) { | ||
assertEquals(str, (str.parseMiraiCode()[0] as PlainText).content) | ||
} | ||
testPlain("[mirai:at:bad,test]") | ||
testPlain("[mirai:at:bad]") | ||
testPlain("[mirai:at:]") | ||
testPlain("[mirai:at]") | ||
} | ||
|
||
@Test | ||
fun atAll() { | ||
val str = "[mirai:atall]" | ||
assertEquals(AtAll, str.parseMiraiCode()[0]) | ||
} | ||
|
||
@Test | ||
fun poke() { | ||
assertEquals(PokeMessage.Poke, PokeMessage.Poke.toString().parseMiraiCode()[0]) | ||
} | ||
|
||
@Test | ||
fun vipFace() { | ||
val instance = VipFace(AiXin, 1) | ||
assertEquals(instance, instance.toString().parseMiraiCode()[0]) | ||
} | ||
|
||
@Test | ||
fun image() { | ||
val instance = Image("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai") | ||
assertEquals(instance, instance.toString().parseMiraiCode()[0]) | ||
} | ||
|
||
@Test | ||
fun flash() { | ||
val instance = Image("{01E9451B-70ED-EAE3-B37C-101F1EEBF5B5}.mirai").flash() | ||
assertEquals(instance, instance.toString().parseMiraiCode()[0]) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters