@@ -5,42 +5,140 @@ import kotlinx.coroutines.withContext
55import net.lz1998.mirai.alias.BMessage
66import net.mamoe.mirai.Bot
77import net.mamoe.mirai.contact.Contact
8+ import net.mamoe.mirai.contact.Group
89import net.mamoe.mirai.getGroupOrNull
910import net.mamoe.mirai.message.data.*
11+ import net.mamoe.mirai.message.uploadAsGroupVoice
1012import net.mamoe.mirai.message.uploadAsImage
1113import java.net.URL
14+ import javax.xml.parsers.DocumentBuilderFactory
1215
1316val MSG_EMPTY = PlainText (" " )
1417
15- suspend fun BMessage.toMiraiMessage (bot : Bot , contact : Contact ): Message {
16- return when (this .type) {
17- " text" -> PlainText (dataMap[" text" ] ? : " " )
18- " face" -> dataMap[" id" ]?.toInt()?.let { Face (it) } ? : MSG_EMPTY
19- " image" -> try {
20- withContext(Dispatchers .IO ) {
21- val img = URL (dataMap[" url" ] ? : dataMap[" file" ]
22- ? : " " ).openConnection().getInputStream().uploadAsImage(contact)
23- if (dataMap[" type" ] == " flash" ) img.flash() else img
18+
19+ suspend fun protoMessageToMiraiMessage (msgList : List <BMessage >, bot : Bot , contact : Contact , notConvert : Boolean ): List <Message > {
20+ val messageChain = mutableListOf<Message >()
21+ msgList.forEach {
22+ when (it.type) {
23+ " text" -> {
24+ if (notConvert) {
25+ messageChain.add(protoTextToMiraiText(it.dataMap))
26+ } else {
27+ val text = it.dataMap[" text" ] ? : return @forEach
28+ messageChain.addAll(rawMessageToMiraiMessage(text, bot, contact))
29+ }
30+ }
31+ " face" -> messageChain.add(protoFaceToMiraiFace(it.dataMap))
32+ " image" -> messageChain.add(protoImageToMiraiImage(it.dataMap, contact))
33+ " at" -> messageChain.add(protoAtToMiraiAt(it.dataMap, bot, contact))
34+ " record" -> messageChain.add(protoVoiceToMiraiVoice(it.dataMap, contact))
35+ " voice" -> messageChain.add(protoVoiceToMiraiVoice(it.dataMap, contact))
36+ else -> MSG_EMPTY
37+ }
38+ }
39+ return messageChain
40+ }
41+
42+
43+ fun protoTextToMiraiText (dataMap : Map <String , String >): Message {
44+ return PlainText (dataMap[" text" ] ? : " " )
45+ }
46+
47+ suspend fun protoImageToMiraiImage (dataMap : Map <String , String >, contact : Contact ): Message {
48+ return try {
49+ withContext(Dispatchers .IO ) {
50+ val img = URL (dataMap[" url" ] ? : dataMap[" file" ]
51+ ? : " " ).openConnection().getInputStream().uploadAsImage(contact)
52+ if (dataMap[" type" ] == " flash" ) img.flash() else img
53+ }
54+ } catch (e: Exception ) {
55+ MSG_EMPTY
56+ }
57+ }
58+
59+ fun protoAtToMiraiAt (dataMap : Map <String , String >, bot : Bot , contact : Contact ): Message {
60+ return if (dataMap[" qq" ] == " all" )
61+ AtAll
62+ else
63+ dataMap[" qq" ]?.toLong()?.let { userId -> bot.getGroupOrNull(contact.id)?.getOrNull(userId)?.let { At (it) } }
64+ ? : MSG_EMPTY
65+ }
66+
67+ fun protoFaceToMiraiFace (dataMap : Map <String , String >): Message {
68+ return dataMap[" id" ]?.toInt()?.let { Face (it) } ? : MSG_EMPTY
69+ }
70+
71+ suspend fun protoVoiceToMiraiVoice (dataMap : Map <String , String >, contact : Contact ): Message {
72+ when (contact) {
73+ is Group -> {
74+ val url = dataMap[" url" ] ? : return MSG_EMPTY
75+ return try {
76+ withContext(Dispatchers .IO ) {
77+ URL (url).openStream().uploadAsGroupVoice(contact)
78+ }
79+ } catch (e: Exception ) {
80+ MSG_EMPTY
2481 }
25- } catch (e: Exception ) {
26- MSG_EMPTY
2782 }
28- " at" -> {
29- if (dataMap[" qq" ] == " all" )
30- AtAll
31- else
32- dataMap[" qq" ]?.toLong()?.let { userId -> bot.getGroupOrNull(contact.id)?.getOrNull(userId)?.let { At (it) } }
33- ? : MSG_EMPTY
83+ else -> return MSG_EMPTY
84+ }
85+
86+ }
87+
88+ suspend fun rawMessageToMiraiMessage (str : String , bot : Bot , contact : Contact ): List <Message > {
89+ val messageList = mutableListOf<Message >()
90+ var str = str
91+ val re = Regex (" <[\\ s\\ S]+?/>" )
92+ val textList = re.split(str).toMutableList()
93+ val codeList = re.findAll(str).map { it.value }.toMutableList()
94+ while (textList.isNotEmpty() || codeList.isNotEmpty()) {
95+ if (textList.isNotEmpty() && str.startsWith(textList.first())) {
96+ val text = textList.first()
97+ textList.removeFirst()
98+ str = str.substring(text.length)
99+ messageList.add(PlainText (text))
100+ }
101+ if (codeList.isNotEmpty() && str.startsWith(codeList.first())) {
102+ val code = codeList.first()
103+ codeList.removeFirst()
104+ str = str.substring(code.length)
105+ // decode xml
106+ val builderFactory = DocumentBuilderFactory .newInstance()
107+ val docBuilder = builderFactory.newDocumentBuilder()
108+ val node = docBuilder.parse(code.byteInputStream()).firstChild
109+
110+ val dataMap = mutableMapOf<String , String >()
111+ while (node.attributes.length > 0 ) {
112+ val item = node.attributes.item(0 )
113+ dataMap[item.nodeName] = item.nodeValue
114+ node.attributes.removeNamedItem(item.nodeName)
115+ }
116+ when (node.nodeName) {
117+ " at" -> messageList.add(protoAtToMiraiAt(dataMap, bot, contact))
118+ " image" -> messageList.add(protoImageToMiraiImage(dataMap, contact))
119+ " face" -> messageList.add(protoFaceToMiraiFace(dataMap))
120+ " text" -> messageList.add(protoTextToMiraiText(dataMap))
121+ " record" -> messageList.add(protoVoiceToMiraiVoice(dataMap, contact))
122+ " voice" -> messageList.add(protoVoiceToMiraiVoice(dataMap, contact))
123+ }
34124 }
35- else -> MSG_EMPTY
125+
36126 }
127+ return messageList
37128}
38129
39130
40- fun MessageChain.toRawMessage (): String {
41- var rawMessage = " "
42- this .forEachContent { rawMessage + = it.contentToString() }
43- return rawMessage
131+ suspend fun MessageChain.toRawMessage (): String {
132+ return this .map {
133+ when (it) {
134+ is PlainText -> it.content
135+ is At -> """ <at qq="${it.target} "/>"""
136+ is Image -> """ <image url="${it.queryUrl()} "/>"""
137+ is Voice -> """ <voice url="${it.url} "/>"""
138+ is Face -> """ <face id="${it.id} "/>"""
139+ else -> " "
140+ }
141+ }.joinToString(" " )
44142}
45143
46144suspend fun MessageChain.toOnebotMessage (): List <BMessage > {
0 commit comments