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
|
package cn.rtast.bldm.client
|
||||||
|
|
||||||
import cn.rtast.bldm.client.util.fromJson
|
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.client.util.sendPacket
|
||||||
import cn.rtast.bldm.codec.event.DanmuEventDispatcher
|
import cn.rtast.bldm.codec.event.DanmuEventDispatcher
|
||||||
import cn.rtast.bldm.codec.protocol.codec.PacketDecoder
|
import cn.rtast.bldm.codec.protocol.codec.PacketDecoder
|
||||||
import cn.rtast.bldm.codec.protocol.codec.PacketEncoder
|
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.codec.util.signWbi
|
||||||
import cn.rtast.bldm.dto.BldmConstant
|
import cn.rtast.bldm.dto.*
|
||||||
import cn.rtast.bldm.dto.DMServerConf
|
import io.ktor.client.*
|
||||||
import cn.rtast.bldm.dto.RealRoomId
|
import io.ktor.client.plugins.*
|
||||||
import cn.rtast.bldm.dto.UserNavData
|
|
||||||
import io.ktor.client.plugins.websocket.*
|
import io.ktor.client.plugins.websocket.*
|
||||||
import io.ktor.client.request.*
|
import io.ktor.client.request.*
|
||||||
import io.ktor.client.statement.*
|
import io.ktor.client.statement.*
|
||||||
@@ -31,6 +30,16 @@ public class BldmClient internal constructor(
|
|||||||
) : DanmuEventDispatcher(), AutoCloseable {
|
) : DanmuEventDispatcher(), AutoCloseable {
|
||||||
private companion object {
|
private companion object {
|
||||||
private val HEARTBEAT_INTERVAL = 30.seconds
|
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()
|
private val packetEncoder = PacketEncoder()
|
||||||
@@ -39,8 +48,12 @@ public class BldmClient internal constructor(
|
|||||||
private var connectionJob: Job? = null
|
private var connectionJob: Job? = null
|
||||||
private var session: DefaultClientWebSocketSession? = 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() {
|
private suspend fun internalConnect() {
|
||||||
val parsedCookie = parseBuvidAndUid(cookie ?: "")
|
|
||||||
val realRoomId = httpClient.get(BldmConstant.REAL_ROOM_ID_URL + "?id=$roomId")
|
val realRoomId = httpClient.get(BldmConstant.REAL_ROOM_ID_URL + "?id=$roomId")
|
||||||
.bodyAsText().fromJson<RealRoomId>()
|
.bodyAsText().fromJson<RealRoomId>()
|
||||||
val navData = httpClient.get(BldmConstant.USER_NAV_URL)
|
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") {
|
val serverConf = httpClient.get(BldmConstant.DM_SERVER_CONF_URL + "?$wbi") {
|
||||||
cookie?.let { header(HttpHeaders.Cookie, it) }
|
cookie?.let { header(HttpHeaders.Cookie, it) }
|
||||||
}.bodyAsText().fromJson<DMServerConf>().data
|
}.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) {
|
httpClient.webSocket(serverConf.hostList.first().tlsWsAddress) {
|
||||||
session = this
|
session = this
|
||||||
val authPacket = packetEncoder.authPacket(
|
val authPacket = packetEncoder.authPacket(
|
||||||
parsedCookie.second ?: 0,
|
uid, realRoomId.data.roomId, buvid, serverConf.token
|
||||||
realRoomId.data.roomId,
|
|
||||||
parsedCookie.first ?: "",
|
|
||||||
serverConf.token
|
|
||||||
)
|
)
|
||||||
sendPacket(authPacket)
|
sendPacket(authPacket)
|
||||||
val heartbeatJob = launch {
|
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"
|
|
||||||
+1
-1
@@ -5,7 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
package cn.rtast.bldm.codec.util
|
package cn.rtast.bldm.client.util
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get buvid and uid from a cookie
|
* get buvid and uid from a cookie
|
||||||
@@ -9,14 +9,12 @@ package test
|
|||||||
|
|
||||||
import cn.rtast.bldm.client.BLDMClient
|
import cn.rtast.bldm.client.BLDMClient
|
||||||
import cn.rtast.bldm.codec.event.DanmuEvent
|
import cn.rtast.bldm.codec.event.DanmuEvent
|
||||||
import kotlinx.coroutines.delay
|
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import kotlinx.io.buffered
|
import kotlinx.io.buffered
|
||||||
import kotlinx.io.files.Path
|
import kotlinx.io.files.Path
|
||||||
import kotlinx.io.files.SystemFileSystem
|
import kotlinx.io.files.SystemFileSystem
|
||||||
import kotlinx.io.readString
|
import kotlinx.io.readString
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.time.Duration.Companion.seconds
|
|
||||||
|
|
||||||
class TestClient {
|
class TestClient {
|
||||||
|
|
||||||
@@ -25,7 +23,7 @@ class TestClient {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `test bldm client`() = runTest {
|
fun `test bldm client`() = runTest {
|
||||||
val client = BLDMClient(7777, cookie)
|
val client = BLDMClient(55, null)
|
||||||
client.on<DanmuEvent.HeartbeatEvent> { println("Heartbeat") }
|
client.on<DanmuEvent.HeartbeatEvent> { println("Heartbeat") }
|
||||||
client.on<DanmuEvent.AuthReplyEvent> { println("AuthReply") }
|
client.on<DanmuEvent.AuthReplyEvent> { println("AuthReply") }
|
||||||
client.on<DanmuEvent.MessageEvent> { println(it.content) }
|
client.on<DanmuEvent.MessageEvent> { println(it.content) }
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ package cn.rtast.bldm.dto
|
|||||||
public object BldmConstant {
|
public object BldmConstant {
|
||||||
public const val REAL_ROOM_ID_URL: String = "https://api.live.bilibili.com/room/v1/Room/room_init"
|
public const val REAL_ROOM_ID_URL: String = "https://api.live.bilibili.com/room/v1/Room/room_init"
|
||||||
public const val USER_NAV_URL: String = "https://api.bilibili.com/x/web-interface/nav"
|
public const val USER_NAV_URL: String = "https://api.bilibili.com/x/web-interface/nav"
|
||||||
|
public const val BUVID_URL: String = "https://api.bilibili.com/x/web-frontend/getbuvid"
|
||||||
public const val DM_SERVER_CONF_URL: String =
|
public const val DM_SERVER_CONF_URL: String =
|
||||||
"https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo"
|
"https://api.live.bilibili.com/xlive/web-room/v1/index/getDanmuInfo"
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* Copyright © 2026 RTAkland
|
||||||
|
* Author: RTAkland
|
||||||
|
* Date: 2026/8/31
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
package cn.rtast.bldm.dto
|
||||||
|
|
||||||
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
public data class Buvid(val data: BuvidData) {
|
||||||
|
@Serializable
|
||||||
|
public data class BuvidData(val buvid: String)
|
||||||
|
}
|
||||||
+13
-1
@@ -20,12 +20,24 @@ subprojects {
|
|||||||
|
|
||||||
publishing {
|
publishing {
|
||||||
repositories {
|
repositories {
|
||||||
maven("https://repo.maven.rtast.cn/snapshots") {
|
maven("https://repo.maven.rtast.cn/releases") {
|
||||||
|
name = "RTAST-PKG"
|
||||||
credentials {
|
credentials {
|
||||||
username = "RTAkland"
|
username = "RTAkland"
|
||||||
password = System.getenv("PUBLISH_TOKEN")
|
password = System.getenv("PUBLISH_TOKEN")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
maven("https://repo.rtast.cn/packages") {
|
||||||
|
name = "RTAST-GIT"
|
||||||
|
credentials(HttpHeaderCredentials::class) {
|
||||||
|
name = "Authorization"
|
||||||
|
value = "Bearer ${System.getenv("PUBLISH_TOKEN")}"
|
||||||
|
}
|
||||||
|
|
||||||
|
authentication {
|
||||||
|
create<HttpHeaderAuthentication>("header")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+1
-1
@@ -2,4 +2,4 @@ kotlin.code.style=official
|
|||||||
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError
|
org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=1024m -XX:+HeapDumpOnOutOfMemoryError
|
||||||
kotlin.native.ignoreDisabledTargets=true
|
kotlin.native.ignoreDisabledTargets=true
|
||||||
|
|
||||||
libVersion=0.1.0
|
libVersion=0.1.1
|
||||||
Reference in New Issue
Block a user