Skip to content

Commit 1afa6a2

Browse files
authored
Merge pull request #4 from lz1998/master
update
2 parents f3fb537 + 4cda295 commit 1afa6a2

File tree

9 files changed

+253
-14
lines changed

9 files changed

+253
-14
lines changed

build.gradle.kts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ plugins {
2121
id("org.springframework.boot") version "2.3.4.RELEASE"
2222
id("io.spring.dependency-management") version "1.0.10.RELEASE"
2323
id("com.google.protobuf") version "0.8.13"
24+
25+
kotlin("plugin.serialization") version "1.4.10"
2426
kotlin("jvm") version "1.4.0"
2527
kotlin("plugin.spring") version "1.4.0"
2628
}
2729

2830
group = "net.lz1998"
29-
version = "0.0.6"
31+
version = "0.0.8"
3032
java.sourceCompatibility = JavaVersion.VERSION_1_8
3133

3234
configurations {
@@ -46,6 +48,8 @@ repositories {
4648
}
4749

4850
dependencies {
51+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0-RC2")
52+
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0-RC")
4953
implementation("net.mamoe:mirai-core-qqandroid:1.3.1")
5054
implementation("com.squareup.okhttp3:okhttp:4.8.0")
5155
// implementation("com.google.protobuf:protobuf-javalite:3.8.0")
@@ -56,6 +60,7 @@ dependencies {
5660
// implementation("com.googlecode.protobuf:protobuf-java-format:1.2")
5761

5862
implementation("org.springframework.boot:spring-boot-starter-web")
63+
implementation("org.springframework.boot:spring-boot-starter-security")
5964
implementation("com.fasterxml.jackson.module:jackson-module-kotlin")
6065
implementation("org.jetbrains.kotlin:kotlin-reflect")
6166
implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
@@ -76,7 +81,7 @@ protobuf {
7681
}
7782
generateProtoTasks {
7883
all().forEach {
79-
it.builtins{
84+
it.builtins {
8085
// remove("java")
8186
// id("java"){
8287
// option("lite")

src/main/kotlin/net/lz1998/mirai/SpringMiraiClientApplication.kt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ import net.lz1998.mirai.properties.ClientProperties
44
import org.springframework.boot.autoconfigure.SpringBootApplication
55
import org.springframework.boot.context.properties.EnableConfigurationProperties
66
import org.springframework.boot.runApplication
7-
import org.springframework.context.annotation.Bean
8-
import org.springframework.context.annotation.Configuration
9-
import org.springframework.http.converter.protobuf.ProtobufHttpMessageConverter
7+
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity
108

9+
@EnableWebSecurity
1110
@SpringBootApplication
1211
@EnableConfigurationProperties(ClientProperties::class)
1312
class SpringMiraiClientApplication

src/main/kotlin/net/lz1998/mirai/entity/RemoteBot.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ interface RemoteBot {
1717
suspend fun onRemoteApi(req: BFrame): BFrame
1818

1919
// 收到机器人事件
20-
fun onBotEvent(botEvent: BotEvent)
20+
suspend fun onBotEvent(botEvent: BotEvent)
2121
}

src/main/kotlin/net/lz1998/mirai/entity/WebSocketBotClient.kt

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import kotlinx.coroutines.launch
66
import kotlinx.coroutines.withContext
77
import net.lz1998.mirai.alias.BFrame
88
import net.lz1998.mirai.alias.BFrameType
9+
import net.lz1998.mirai.ext.fileStrBasedDeviceInfo
910
import net.lz1998.mirai.ext.friendRequestLru
1011
import net.lz1998.mirai.ext.groupRequestLru
1112
import net.lz1998.mirai.ext.messageSourceLru
@@ -97,7 +98,7 @@ class WebsocketBotClient(override var botId: Long, override var password: String
9798
override suspend fun initBot() {
9899
wsClient = httpClient.newWebSocket(wsRequest, wsListener)
99100
bot = Bot(botId, password) {
100-
fileBasedDeviceInfo("device.json")
101+
fileStrBasedDeviceInfo("device.json")
101102
loginSolver = MyLoginSolver
102103
noNetworkLog()
103104
}.alsoLogin()
@@ -124,6 +125,7 @@ class WebsocketBotClient(override var botId: Long, override var password: String
124125
val respBuilder = BFrame.newBuilder()
125126
respBuilder.echo = req.echo
126127
respBuilder.botId = botId
128+
respBuilder.ok = true
127129
when (req.frameType) {
128130
BFrameType.SendPrivateMsgReq -> respBuilder.sendPrivateMsgResp = handleSendPrivateMsg(bot, req.sendPrivateMsgReq)
129131
BFrameType.SendGroupMsgReq -> respBuilder.sendGroupMsgResp = handleSendGroupMsg(bot, req.sendGroupMsgReq)
@@ -144,11 +146,12 @@ class WebsocketBotClient(override var botId: Long, override var password: String
144146
BFrameType.GetGroupListReq -> respBuilder.getGroupListResp = handleGetGroupList(bot, req.getGroupListReq)
145147
BFrameType.GetGroupMemberInfoReq -> respBuilder.getGroupMemberInfoResp = handleGetGroupMemberInfo(bot, req.getGroupMemberInfoReq)
146148
BFrameType.GetGroupMemberListReq -> respBuilder.getGroupMemberListResp = handleGetGroupMemberList(bot, req.getGroupMemberListReq)
149+
else -> respBuilder.ok = false
147150
}
148151
return respBuilder.build()
149152
}
150153

151-
override fun onBotEvent(botEvent: BotEvent) {
154+
override suspend fun onBotEvent(botEvent: BotEvent) {
152155
val eventFrame = botEvent.toFrame() ?: return
153156
// TODO 写二进制还是json?配置
154157
val ok = wsClient.send(eventFrame.toByteArray().toByteString())
Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
package net.lz1998.mirai.ext
2+
3+
import kotlinx.serialization.Required
4+
import kotlinx.serialization.SerialName
5+
import kotlinx.serialization.Serializable
6+
import kotlinx.serialization.Transient
7+
import kotlinx.serialization.json.Json
8+
import net.mamoe.mirai.utils.BotConfigurationBase
9+
import net.mamoe.mirai.utils.Context
10+
import net.mamoe.mirai.utils.ExternalImage
11+
import net.mamoe.mirai.utils.BotConfiguration
12+
import net.mamoe.mirai.utils.ContextImpl
13+
import net.mamoe.mirai.utils.DeviceInfo
14+
import java.io.File
15+
import java.security.MessageDigest
16+
import kotlin.random.Random
17+
import kotlin.random.nextInt
18+
19+
20+
@Serializable
21+
open class MyDeviceInfo() : DeviceInfo() {
22+
constructor(context: Context) : this() {
23+
this.context = context
24+
}
25+
26+
@Transient
27+
final override lateinit var context: Context
28+
override val androidId: ByteArray
29+
get() = androidIdStr.toByteArray()
30+
31+
override val apn: ByteArray
32+
get() = apnStr.toByteArray()
33+
34+
override val baseBand: ByteArray
35+
get() = byteArrayOf()
36+
37+
override val board: ByteArray
38+
get() = boardStr.toByteArray()
39+
40+
override val bootId: ByteArray
41+
get() = bootIdStr.toByteArray()
42+
43+
override val bootloader: ByteArray
44+
get() = bootloaderStr.toByteArray()
45+
46+
override val brand: ByteArray
47+
get() = brandStr.toByteArray()
48+
49+
override val device: ByteArray
50+
get() = deviceStr.toByteArray()
51+
52+
override val display: ByteArray
53+
get() = displayStr.toByteArray()
54+
55+
override val fingerprint: ByteArray
56+
get() = fingerprintStr.toByteArray()
57+
58+
override val imei: String
59+
get() = imeiStr
60+
61+
override val macAddress: ByteArray
62+
get() = macAddressStr.toByteArray()
63+
64+
override val model: ByteArray
65+
get() = modelStr.toByteArray()
66+
67+
override val osType: ByteArray
68+
get() = osTypeStr.toByteArray()
69+
70+
override val procVersion: ByteArray
71+
get() = procVersionStr.toByteArray()
72+
73+
override val product: ByteArray
74+
get() = productStr.toByteArray()
75+
76+
override val simInfo: ByteArray
77+
get() = simInfoStr.toByteArray()
78+
79+
override val wifiBSSID: ByteArray?
80+
get() = wifiBSSIDStr.toByteArray()
81+
82+
override val wifiSSID: ByteArray?
83+
get() = wifiSSIDStr.toByteArray()
84+
override val version: Version
85+
get() = Version
86+
87+
88+
@Serializable
89+
object Version : DeviceInfo.Version {
90+
override val incremental: ByteArray = "5891938".toByteArray()
91+
override val release: ByteArray = "10".toByteArray()
92+
override val codename: ByteArray = "REL".toByteArray()
93+
override val sdk: Int = 29
94+
}
95+
96+
@Required
97+
@SerialName("androidId")
98+
var androidIdStr: String = "SMC.${getRandomString(6, '0'..'9')}.001"
99+
100+
@Required
101+
@SerialName("apn")
102+
var apnStr: String = "wifi"
103+
104+
@Required
105+
@SerialName("board")
106+
var boardStr: String = "smc"
107+
108+
@SerialName("bootId")
109+
@Required
110+
var bootIdStr: String = ExternalImage.generateUUID(getRandomByteArray(16).md5(0, 16))
111+
112+
@Required
113+
@SerialName("bootloader")
114+
var bootloaderStr: String = "unknown"
115+
116+
@Required
117+
@SerialName("brand")
118+
var brandStr: String = "pbbot"
119+
120+
@Required
121+
@SerialName("device")
122+
var deviceStr: String = "smc"
123+
124+
@Required
125+
@SerialName("display")
126+
var displayStr: String = androidIdStr
127+
128+
@Required
129+
@SerialName("fingerprint")
130+
var fingerprintStr: String = "pbbot/smc/smc:10/SMC.200122.001/${getRandomString(7, '0'..'9')}:user/release-keys"
131+
132+
@Required
133+
@SerialName("macAddress")
134+
var macAddressStr: String = "02:00:00:00:00:00"
135+
136+
@Required
137+
@SerialName("model")
138+
var modelStr: String = "smc"
139+
140+
@Required
141+
@SerialName("osType")
142+
var osTypeStr: String = "android"
143+
144+
@Required
145+
@SerialName("procVersion")
146+
var procVersionStr: String = "Linux version 3.0.31-${getRandomString(8, 'a'..'z')} ([email protected])"
147+
148+
@Required
149+
@SerialName("product")
150+
var productStr: String = "smc"
151+
152+
@Required
153+
@SerialName("simInfo")
154+
var simInfoStr: String = "T-Mobile"
155+
156+
@Required
157+
@SerialName("wifiBSSID")
158+
var wifiBSSIDStr: String = "02:00:00:00:00:00"
159+
160+
@Required
161+
@SerialName("wifiSSID")
162+
var wifiSSIDStr: String = "<unknown ssid>"
163+
164+
@Required
165+
@SerialName("imei")
166+
var imeiStr: String = getRandomString(15, '0'..'9')
167+
168+
@Required
169+
@SerialName("imsiMd5")
170+
override val imsiMd5: ByteArray = getRandomByteArray(16).md5(0, 16)
171+
172+
}
173+
174+
@JvmOverloads
175+
@BotConfigurationBase.ConfigurationDsl
176+
fun BotConfiguration.fileStrBasedDeviceInfo(filepath: String = "device.json") {
177+
deviceInfo = getFileStrBasedDeviceInfoSupplier(filepath)
178+
}
179+
180+
fun BotConfiguration.getFileStrBasedDeviceInfoSupplier(filename: String): ((Context) -> DeviceInfo)? {
181+
return {
182+
File(filename).loadStrAsDeviceInfo(json, it)
183+
}
184+
}
185+
186+
/**
187+
* 加载一个设备信息. 若文件不存在或为空则随机并创建一个设备信息保存.
188+
*/
189+
fun File.loadStrAsDeviceInfo(json: Json, context: Context = ContextImpl()): DeviceInfo {
190+
if (!this.exists() || this.length() == 0L) {
191+
return MyDeviceInfo(context).also {
192+
this.writeText(json.encodeToString(MyDeviceInfo.serializer(), it))
193+
}
194+
}
195+
return json.decodeFromString(MyDeviceInfo.serializer(), this.readText()).also {
196+
it.context = context
197+
}
198+
}
199+
200+
201+
fun getRandomString(length: Int, charRange: CharRange): String =
202+
String(CharArray(length) { charRange.random() })
203+
204+
fun getRandomByteArray(length: Int): ByteArray = ByteArray(length) { Random.nextInt(0..255).toByte() }
205+
206+
fun ByteArray.md5(offset: Int, length: Int): ByteArray {
207+
this.checkOffsetAndLength(offset, length)
208+
return MessageDigest.getInstance("MD5").apply { update(this@md5, offset, length) }.digest()
209+
}
210+
211+
fun ByteArray.checkOffsetAndLength(offset: Int, length: Int) {
212+
require(offset >= 0) { "offset shouldn't be negative: $offset" }
213+
require(length >= 0) { "length shouldn't be negative: $length" }
214+
require(offset + length <= this.size) { "offset ($offset) + length ($length) > array.size (${this.size})" }
215+
}

src/main/kotlin/net/lz1998/mirai/utils/EventConverter.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,15 @@ import net.mamoe.mirai.event.events.*
55
import net.mamoe.mirai.message.*
66
import net.mamoe.mirai.message.data.*
77

8-
fun BotEvent.toFrame(): BFrame? = when (this) {
8+
suspend fun BotEvent.toFrame(): BFrame? = when (this) {
99
is GroupMessageEvent -> this.toProtoMessage().toProtoFrame(this.bot.id)
1010
is FriendMessageEvent -> this.toProtoMessage().toProtoFrame(this.bot.id)
1111
is MemberJoinEvent -> this.toProtoMessage().toProtoFrame(this.bot.id)
1212
is MemberLeaveEvent -> this.toProtoMessage().toProtoFrame(this.bot.id)
1313
else -> null
1414
}
1515

16-
fun GroupMessageEvent.toProtoMessage(): BGroupMessageEvent {
16+
suspend fun GroupMessageEvent.toProtoMessage(): BGroupMessageEvent {
1717
val sender = BGroupMessageSender.newBuilder()
1818
.setUserId(this.sender.id)
1919
.setNickname(this.sender.nick)
@@ -43,7 +43,7 @@ fun GroupMessageEvent.toProtoMessage(): BGroupMessageEvent {
4343
.build()
4444
}
4545

46-
fun FriendMessageEvent.toProtoMessage(): BPrivateMessageEvent {
46+
suspend fun FriendMessageEvent.toProtoMessage(): BPrivateMessageEvent {
4747
val sender = BPrivateMessageSender.newBuilder()
4848
.setUserId(this.sender.id)
4949
.setNickname(this.sender.nick)

src/main/kotlin/net/lz1998/mirai/utils/MsgConverter.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,14 @@ fun MessageChain.toRawMessage(): String {
4343
return rawMessage
4444
}
4545

46-
fun MessageChain.toOnebotMessage(): List<BMessage> {
46+
suspend fun MessageChain.toOnebotMessage(): List<BMessage> {
4747
val messageChain = mutableListOf<BMessage>()
4848
this.forEachContent { content ->
4949
val message = when (content) {
5050
is At -> BMessage.newBuilder().setType("at").putAllData(mapOf("qq" to content.target.toString())).build()
5151
is PlainText -> BMessage.newBuilder().setType("text").putAllData(mapOf("text" to content.content)).build()
5252
is Face -> BMessage.newBuilder().setType("face").putAllData(mapOf("id" to content.id.toString())).build()
53-
is Image -> BMessage.newBuilder().setType("image").putAllData(mapOf("file" to content.imageId)).build()
53+
is Image -> BMessage.newBuilder().setType("image").putAllData(mapOf("file" to content.queryUrl())).build()
5454
is Voice -> BMessage.newBuilder().setType("record").putAllData(mapOf("file" to content.fileName)).build()
5555
else -> BMessage.newBuilder().setType("unknown").build()
5656
}

src/main/resources/application.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,10 @@ server:
22
port: 9000
33
bot:
44
client:
5-
ws-url: "ws://localhost:8081/ws/test/"
5+
ws-url: "ws://localhost:8081/ws/test/"
6+
7+
spring:
8+
security:
9+
user:
10+
name: admin
11+
password: 123456
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<title>机器人管理</title>
6+
</head>
7+
<body>
8+
<div>请检查前端文件是否缺失。</div>
9+
<div>可以去<a href="https://github.com/protobufbot/spring-mirai-client-ui">这里</a>找到前端项目。</div>
10+
</body>
11+
</html>

0 commit comments

Comments
 (0)