@@ -5,42 +5,140 @@ import kotlinx.coroutines.withContext
5
5
import net.lz1998.mirai.alias.BMessage
6
6
import net.mamoe.mirai.Bot
7
7
import net.mamoe.mirai.contact.Contact
8
+ import net.mamoe.mirai.contact.Group
8
9
import net.mamoe.mirai.getGroupOrNull
9
10
import net.mamoe.mirai.message.data.*
11
+ import net.mamoe.mirai.message.uploadAsGroupVoice
10
12
import net.mamoe.mirai.message.uploadAsImage
11
13
import java.net.URL
14
+ import javax.xml.parsers.DocumentBuilderFactory
12
15
13
16
val MSG_EMPTY = PlainText (" " )
14
17
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
24
81
}
25
- } catch (e: Exception ) {
26
- MSG_EMPTY
27
82
}
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
+ }
34
124
}
35
- else -> MSG_EMPTY
125
+
36
126
}
127
+ return messageList
37
128
}
38
129
39
130
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(" " )
44
142
}
45
143
46
144
suspend fun MessageChain.toOnebotMessage (): List <BMessage > {
0 commit comments