Support anonymous connect to ws server
This commit is contained in:
8 files changed
+56
-42
No files matched your search
@@ -7,16 +7,15 @@
|
||||
package cn.rtast.bldm.client
|
||||
|
||||
import cn.rtast.bldm.client.util.fromJson
|
||||
import cn.rtast.bldm.client.util.parseBuvidAndUid
|
||||
import cn.rtast.bldm.client.util.sendPacket
|
||||
import cn.rtast.bldm.codec.event.DanmuEventDispatcher
|
||||
import cn.rtast.bldm.codec.protocol.codec.PacketDecoder
|
||||
import cn.rtast.bldm.codec.protocol.codec.PacketEncoder
|
||||
import cn.rtast.bldm.codec.util.parseBuvidAndUid
|
||||
import cn.rtast.bldm.codec.util.signWbi
|
||||
import cn.rtast.bldm.dto.BldmConstant
|
||||
import cn.rtast.bldm.dto.DMServerConf
|
||||
import cn.rtast.bldm.dto.RealRoomId
|
||||
import cn.rtast.bldm.dto.UserNavData
|
||||
import cn.rtast.bldm.dto.*
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.plugins.*
|
||||
import io.ktor.client.plugins.websocket.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
@@ -31,6 +30,16 @@ public class BldmClient internal constructor(
|
||||
) : DanmuEventDispatcher(), AutoCloseable {
|
||||
private companion object {
|
||||
private val HEARTBEAT_INTERVAL = 30.seconds
|
||||
private const val USER_AGENT =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36"
|
||||
}
|
||||
|
||||
private val httpClient = HttpClient {
|
||||
install(WebSockets)
|
||||
|
||||
defaultRequest {
|
||||
header(HttpHeaders.UserAgent, USER_AGENT)
|
||||
}
|
||||
}
|
||||
|
||||
private val packetEncoder = PacketEncoder()
|
||||
@@ -39,8 +48,12 @@ public class BldmClient internal constructor(
|
||||
private var connectionJob: Job? = null
|
||||
private var session: DefaultClientWebSocketSession? = null
|
||||
|
||||
private suspend fun getBuvidFromApi(): String =
|
||||
httpClient.get(BldmConstant.BUVID_URL)
|
||||
.bodyAsText().fromJson<Buvid>()
|
||||
.data.buvid
|
||||
|
||||
private suspend fun internalConnect() {
|
||||
val parsedCookie = parseBuvidAndUid(cookie ?: "")
|
||||
val realRoomId = httpClient.get(BldmConstant.REAL_ROOM_ID_URL + "?id=$roomId")
|
||||
.bodyAsText().fromJson<RealRoomId>()
|
||||
val navData = httpClient.get(BldmConstant.USER_NAV_URL)
|
||||
@@ -49,14 +62,13 @@ public class BldmClient internal constructor(
|
||||
val serverConf = httpClient.get(BldmConstant.DM_SERVER_CONF_URL + "?$wbi") {
|
||||
cookie?.let { header(HttpHeaders.Cookie, it) }
|
||||
}.bodyAsText().fromJson<DMServerConf>().data
|
||||
|
||||
val parsedCookie = parseBuvidAndUid(cookie ?: "")
|
||||
val buvid = if (cookie == null) getBuvidFromApi() else parsedCookie.first!!
|
||||
val uid = if (cookie == null) 0 else parsedCookie.second!!
|
||||
httpClient.webSocket(serverConf.hostList.first().tlsWsAddress) {
|
||||
session = this
|
||||
val authPacket = packetEncoder.authPacket(
|
||||
parsedCookie.second ?: 0,
|
||||
realRoomId.data.roomId,
|
||||
parsedCookie.first ?: "",
|
||||
serverConf.token
|
||||
uid, realRoomId.data.roomId, buvid, serverConf.token
|
||||
)
|
||||
sendPacket(authPacket)
|
||||
val heartbeatJob = launch {
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.client
|
||||
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.plugins.defaultRequest
|
||||
import io.ktor.client.plugins.websocket.*
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.http.HttpHeaders
|
||||
|
||||
internal val httpClient = HttpClient {
|
||||
install(WebSockets)
|
||||
|
||||
defaultRequest {
|
||||
header(HttpHeaders.UserAgent, USER_AGENT)
|
||||
}
|
||||
}
|
||||
|
||||
internal const val USER_AGENT =
|
||||
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/151.0.0.0 Safari/537.36"
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright © 2026 RTAkland
|
||||
* Author: RTAkland
|
||||
* Date: 2026/8/30
|
||||
*/
|
||||
|
||||
|
||||
package cn.rtast.bldm.client.util
|
||||
|
||||
/**
|
||||
* get buvid and uid from a cookie
|
||||
* first -> buvid
|
||||
* second -> uid
|
||||
*/
|
||||
public fun parseBuvidAndUid(cookie: String): Pair<String?, Long?> {
|
||||
if (cookie.isBlank()) return Pair(null, null)
|
||||
var buvid: String? = null
|
||||
var uid: Long? = null
|
||||
cookie.split(';').forEach { entry ->
|
||||
val parts = entry.split('=', limit = 2)
|
||||
if (parts.size == 2) {
|
||||
when (parts[0].trim()) {
|
||||
"buvid3" -> buvid = parts[1].trim()
|
||||
"DedeUserID" -> uid = parts[1].trim().toLongOrNull()
|
||||
}
|
||||
}
|
||||
}
|
||||
return buvid to uid
|
||||
}
|
||||
@@ -9,14 +9,12 @@ package test
|
||||
|
||||
import cn.rtast.bldm.client.BLDMClient
|
||||
import cn.rtast.bldm.codec.event.DanmuEvent
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.test.runTest
|
||||
import kotlinx.io.buffered
|
||||
import kotlinx.io.files.Path
|
||||
import kotlinx.io.files.SystemFileSystem
|
||||
import kotlinx.io.readString
|
||||
import kotlin.test.Test
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class TestClient {
|
||||
|
||||
@@ -25,7 +23,7 @@ class TestClient {
|
||||
|
||||
@Test
|
||||
fun `test bldm client`() = runTest {
|
||||
val client = BLDMClient(7777, cookie)
|
||||
val client = BLDMClient(55, null)
|
||||
client.on<DanmuEvent.HeartbeatEvent> { println("Heartbeat") }
|
||||
client.on<DanmuEvent.AuthReplyEvent> { println("AuthReply") }
|
||||
client.on<DanmuEvent.MessageEvent> { println(it.content) }
|
||||
|
||||
Reference in New Issue
Block a user